【过河问题】阿里笔试
题目描述: 有
N
N
N个人一起过河,但只有一条船,每条船每次最多只能容纳两人。过河的速度等于两人中体重最大的那一个人的体重,若只有一人过河,则速度即为该人体重。现给出这
N
N
N个人的体重,请你计算出这
N
N
N个人过河的最短时间。
思路:将每个人的过河时间按升序排好序。
- 如果只有一个人过河,那么过河时间为该人体重。
- 如果两个人过河,那么过河时间为两人中体重最大的那个。
- 如果三个人过河,那最优策略应该为最慢和最快的人过河(时间 T 2 T2 T2),最快的返回(时间 T 0 T0 T0),然后最快和次慢的人过河(时间 T 1 T1 T1),那么过河时间应该为三人单独过河的时间总和 T 0 + T 1 + T 2 T0+T1+T2 T0+T1+T2。
- 如果四个人过河,过河时间分别为
T
0
,
T
1
,
T
2
,
T
3
T0,T1,T2,T3
T0,T1,T2,T3,那么有两种策略:
(1)最快和次快的人过河(时间 T 1 T1 T1),最快的人返回(时间 T 0 T0 T0),然后最慢和次慢的人过河(时间 T 3 T3 T3),次快的人返回(时间 T 1 T1 T1),最后最快和次快的人过河(时间 T 1 T1 T1)。总时间: T 1 + T 0 + T 3 + T 1 + T 1 T1+T0 + T3 +T1+T1 T1+T0+T3+T1+T1
(2)最慢和最快的人过河(时间 T 3 T3 T3),最快的人返回(时间 T 0 T0 T0),然后次慢和最快的人过河(时间 T 2 T2 T2),最快的人返回(时间 T 0 T0 T0),最后最快和次快的人过河(时间 T 1 T1 T1)。总时间: T 3 + T 0 + T 2 + T 0 + T 1 T3+T0+T2+T0+T1 T3+T0+T2+T0+T1
最后一趟总是最快和次快的人过河。因此比较这两种方案哪一种更优,则是比较 2 × T 1 2\times T1 2×T1(第一种)和 T 0 + T 2 T0+T2 T0+T2(第二种)的大小。如果 2 × T 1 > T 0 + T 2 2\times T1>T0+T2 2×T1>T0+T2,则选择第二种方案,反之,这选择第一种,二者相等,则两个方案用时相同。 - 如果 N N N个人过河( N > 4 N>4 N>4),则这个问题可以划为多个四人过河( N N N为奇数,则最后为三人过河)子问题。因为最重的一人过河时间是不会受任何其他人的干扰,因此在这个过程中,应该用最快和次快的人来减少返程的时间,而与最重的人搭配,必然是次重的人,否则次重的人会成为下次最重的人,这样只会加长过河时间。而在四人过河这个子问题中,则可以根据上述提到的两种方案择优而取。
def GuoHe(N,weight):
weight.sort()
if N < 3:
Times = weight[N-1]
return Times
if N == 3:
Times = sum(weight)
return Times
Times = 0
while N >= 4:
T1 = weight[0] + 2*weight[1] + weight[N-1]
T2 = weight[N-1] + weight[N-2] + 2*weight[0]
if T1>T2:
Times = Times + T2
else:
Times = Times + T1
N -= 2
if N==3:
Times = Times + sum(weight[0:3])
return Times
# 最后一趟最快和次快的人过河时间要加上
if N==2:
return Times + weight[1]
# 测试样例的个数
T = int(input())
for i in range(T):
# 人数
N = int(input())
#每人体重
weight = list(map(int,input().split()))
Times = GuoHe(N,weight)
print(Times)
【顺时针打印矩阵】华为笔试
题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下
4
×
4
4\times4
4×4矩阵:
[
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
]
\begin{bmatrix} 1 & 2 & 3 & 4 \\ 5&6&7&8\\9&10&11&12\\13&14&15&16\end{bmatrix}
⎣⎢⎢⎡15913261014371115481216⎦⎥⎥⎤ ,则依次打印出数字
1
,
2
,
3
,
4
,
8
,
12
,
16
,
15
,
14
,
13
,
9
,
5
,
6
,
7
,
11
,
10
1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10
1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。
思路:每次输出完矩阵第一行后,将矩阵进行旋转,再输出第一行。例如
4
×
4
4\times4
4×4矩阵输出第一行后为
[
5
6
7
8
9
10
11
12
13
14
15
16
]
\begin{bmatrix}5&6&7&8\\9&10&11&12\\13&14&15&16\end{bmatrix}
⎣⎡5913610147111581216⎦⎤,将其旋转为
[
8
12
16
7
11
15
6
10
14
5
9
13
]
\begin{bmatrix}8&12&16\\7&11&15\\6&10&14\\5&9&13\end{bmatrix}
⎣⎢⎢⎡8765121110916151413⎦⎥⎥⎤,pop
掉第一行后再旋转为
[
15
14
13
11
10
9
7
6
5
]
\begin{bmatrix}15&14&13\\11&10&9\\7&6&5\end{bmatrix}
⎣⎡15117141061395⎦⎤,再pop
第一行,再旋转,如此反复,知道matrix为空。
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
res = []
while matrix:
res += matrix.pop(0)
if not matrix or not matrix[0]:
break
matrix = self.turn(matrix)
return res
# 将当前矩阵翻转过来,行数变成列数,列数变成行数
def turn(self,matrix):
# 矩阵行数
num_r = len(matrix)
num_c = len(matrix[0])
newmat = []
# 第末列的变成第一行,于是列数倒序。行数正序
for i in range(num_c-1,-1,-1):
newmat2 = []
for j in range(num_r):
newmat2.append(matrix[j][i])
newmat.append(newmat2)
return newmat
【螺旋矩阵输出】
先输入得到一个
n
×
n
n\times n
n×n大小的斐波那契数列(第一项、第二项为1),然后将数列螺旋打印输出,如
n
=
3
n=3
n=3,则输出为
[
1
1
2
21
34
3
13
8
5
]
\begin{bmatrix}1&1&2\\21&34&3\\13&8&5\end{bmatrix}
⎣⎡121131348235⎦⎤。
思路:螺旋式填充这个
n
×
n
n\times n
n×n矩阵。
Python代码如下:
def fb(n):
res = [1,1]
f1 = res[0]
f2 = res[1]
for i in range(2,n):
f1, f2 = f2, f1+f2
res.append(f2)
return res
def printMatrix(res):
n = len(res)
m = int(n**0.5)
arr = [[0]*m for _ in range(m)]
i = 0
j = 0
arr[i][j] = res[0]
num = 1
while num<n:
# 从最上面一行开始
while j+1<m and arr[i][j+1]==0:
arr[i][j+1] = res[num]
j += 1
num += 1
# 从最右一列开始
while i+1<m and arr[i+1][j]==0:
arr[i+1][j] = res[num]
i += 1
num += 1
# 从最下面一行开始
while j-1>=0 and arr[i][j-1]==0:
arr[i][j-1] = res[num]
j -= 1
num += 1
# 从最上面一行开始
while i-1>=0 and arr[i-1][j]==0:
arr[i-1][j] = res[num]
i -= 1
num += 1
return arr
n = int(input())
res = fb(n)
arr = printMatrix(res)
print(arr)
C语言代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int main()
{
int N,i=1;
int a[100] = {1,1};
printf("斐波那契数列长度:");
scanf("%d",&N);
for(i=2;i<N;i++)
{
a[i] = a[i-1] + a[i-2];
}
for(i=0;i<N;i++)
{
printf("%2d\n",a[i]);
}
int m = sqrt(N);
int arr[10][10];
//初始化arr全为0,需头文件string.h
memset(arr,0,sizeof(arr));
int r=0,c = 0;
arr[r][c] = a[0];
int num = 1;
while(num<N)
{
while(c+1<m&&arr[r][c+1]==0)
arr[r][++c] = a[num++];
while(r+1<m&&arr[r+1][c]==0)
arr[++r][c] = a[num++];
while(c-1>=0&&arr[r][c-1]==0)
arr[r][--c] = a[num++];
while(r-1>=0&&arr[r-1][c]==0)
arr[--r][c] = a[num++];
}
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)
printf("%2d",arr[i][j]);
printf("\n");
}
}