1 4 1 2 5 10
17
题目大意:
有n个人想过河,但是他们只有一条能同时载两个人的船,每个人划船渡河的时间不同,当两个人同乘一艘船时,他们划船所用时间按较慢的人的速度计算。问你n个人全部过河所需的最短时间。要注意的是船划过河对岸再回来的时间也需要计算进去。
题目分析:
n=1;n=2;n=3的情况很好分析,当n=3时,渡河的时间刚好是三个人所用时间相加(最快最慢过去,t+=最慢,然后最快回来,t+=最快,然后最快次快过去,t+=次快)所以我们直接从n=4开始,假设他们按划船的速度从慢到快排列是ABCD四人,可以知道,船必须回来才能到达使全部人过去,而回来的人肯定要是已经过河的人中速度最快的那个,那么一去一回就变成了n=3的情况,第一次没有过去的两个人和过去了没返回的一个人时间算了一次,第一次去又返回了的那个人的时间算了两次,也就是说tmin=ta+tb+tc+td+min(a,b,c,d),这是基于两种策略来的
第一种:AB过去,A回来,CD过去,B回来,AB过去(T=B+A+D+B+B)
第二种:AD过去,A回来,AC过去,A回来,AB过去(T=D+A+C+A+B)
这两种策略的最后一步都是AB过去,所以我们可以知道,4个人在选取全局最优策略的前提下,局部问题要过去最慢的两个人所需的时间是2*B+D和A+C+D中的最小值。
这个结论可以继续向更大的n拓展(其实我也不知道为什么,我把我能理解的部分已经讲清楚了。。),所以当n>=4时,我们可以不断借助最快的两个人,让他们运送最慢的两个人过去,当n<4时就直接处理。
代码如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int T,n,m,i,p,q,sum;
int a[1005];
scanf("%d",&T);
while(T--)
{
sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n-1);
while(n>=4)
{
p=2*a[0]+a[n-1]+a[n-2];
q=a[0]+2*a[1]+a[n-1];
if(p>q) sum+=q;//时间加上两种策略中较小的一个
else sum+=p;
n-=2;//最慢的两个人被运过去了
}
if(n==3)
sum+=a[0]+a[1]+a[2];
else if(n==2) sum+=a[1];
else if(n==1) sum+=a[0];
printf("%d\n",sum);
}
return 0;
}