手电筒过河
一。问题:
夜晚n位旅行者要过桥,总共只有一个手电筒,一次最多两人过桥,且过桥必须使用手电筒。每位旅行者单独过桥的所需的时间已知,两人结伴渡桥所用的时间为两人中最长的时间。
求解所有人过桥所用的总时间最短是多少。
二。分析:
因为只有一个手电筒,必定有人过桥之后,还要将手电筒送回来。
若n=1,或n=2 所有人直接过河。
若n=3 ,最快的人往返一次把两个人送过去。
若n=4时,假设四人耗时从少到多依次为a , b, y, z.
那么有两种方案过河,
方案一:ab一起过河,a返回,yz一起过河,b返回接a 耗时b+a+z+b+b
方案二:ay一起过河,a返回,az一起过河,a返回接b 耗时y+a+z+a+b
这两种方案的末状态一定是:最大的两个已经过河,最小的两个留在河这面
两方案的时间差为2b-a-y
当2b>a+y时,采用方案2, 当2b<=a+y时,采用方案1.
若n>4时,该问题相当于两个快的一直在送最慢的两个,因此递归求解,转化成n-2个旅行者的问题。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int p[1100]; int cmp(int a,int b) { return a<b; } int Time(int n) { if(n==1) return p[0]; if(n==2) return p[1]; if(n==3) return p[0]+p[1]+p[2]; if(p[1]*2>=p[0]+p[n-2]) return 2*p[0]+p[n-1]+p[n-2]+Time(n-2); else return 2*p[1]+p[0]+p[n-1]+Time(n-2); } int main() { int T; int n; int i,j; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(p,0,sizeof(p)); for(i=0;i<n;i++) { scanf("%d",&p[i]); } sort(p,p+n,cmp); printf("%d\n",Time(n)); } return 0; }