简介:问题解决思路记录。
问题描述:
n个人要过一座河,只有一条船,每次最多只能通过两个人。 每个人的速度不同,若两人组队,队伍速度等于较慢一人的速度。你要做的是计算这n个人全部通过的最少时间。
思路:
人数小于等于3的情况比较简单,单独处理。
当人数大于3的时候,有两种方法,在介绍方法之前我们先给列表中特定的元素一个代号,假设列表从小到大排序后为list=[0,1,2,...,n] 我们令a=0号元素,b=1号元素,x=n-1号元素,y=n号元素。接下来介绍两种方法:
方法一:ab双摆渡法
先由a、b将船开过去,然后a回来,x和y过去,再由b把船带回来。
此过程所花时间为 b+a+y+b。
方法二:a单摆渡法
由a将y和x摆渡过去,a再把船带回来。
此过程所花时间为 y+a+x+a。
这两个方法的共同点都是一次摆渡两个最大值过去,在不同的情况下这两者的优劣不同,所以要分当前情况下哪一种方案最佳就用哪一种方案。
将两者所用时间对比化简可以发现,当2b<x+a时ab双摆渡法更优,反之则使用a单摆渡法。
如此循环直到队列中人数小于等于3时分情况解决:
人数为0时表示最开始就为0,输出0。
人数为1时表示最开始就为1,输出list[0]。
人数为2时就有可能是经过上述循环的结果了,在上面消耗的总时间t上加入max(list[0],list[1])即可。
人数为3时也有可能是经过上述循环的结果了,在上面消耗的总时间t上加入sum(list)即可。这里的list中仅剩最后三个元素。
由python实现的代码如下:
# 输入
# 多组输入。每组数据的第一行是输入一个n,代表有n(1 <= n && n <= 500)个人,接下来的n个整数,代表着每个人的所需时间。
#
# 输出
# 输出一个整数,代表最优策略所需时间sum。
#
# 示例输入
# 4
# 1
# 10
# 5
# 2
#
# 示例输出
# 17
import sys
i=-1
for line in sys.stdin:
i+=1
if i==0:
n=int(line.split()[0])
arr=[]
else:
a=int(line.split()[0])
arr.append(a)
if i==n:
arr.sort()
break
t=0
right=[]
while(len(arr)>3):#小于等于3的情况比较简单,单独处理
#一次摆渡过去两个最大值
t_i = 0
if 2*arr[1]<arr[0]+arr[-2]:#这一趟中,满足这个条件就使用a,b摆渡法,否则就使用a护送法
right.append(arr.pop())
t_i+=right[-1]#这是+y
right.append(arr.pop())
t_i +=arr[0]+ 2*arr[1]#这是+a+2b
else:
right.append(arr.pop())
t_i += right[-1]#这是+y
right.append(arr.pop())
t_i += right[-1]#这是+x
t_i += 2 *arr[0] # 这是+2a
t+=t_i
l=len(arr)
if l==0:
print(0)
elif l==1:
print(arr[0])
elif l==2:
print(t+max(arr[0],arr[1]))
elif l==3:
print(t+sum(arr))