题目地址:http://codeup.cn/problem.php?id=3296
3296: 过河问题
题目描述
在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。
输入
第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)
输出
输出所有人都过河需要用的最少时间
样例输入
1 4 1 2 5 10
样例输出
17
解题思路
对于一个人,直接过河
对于两个人,一起过河
对于三个人,最快的和任意一个一起过河,最快的回来,最快的和剩余一个一起过河
这里主要分析四个人过河的两种策略
策略一:最快的和任意一个一起过河,然后最快的再回来,再和任意的一个一起过河,然后最快的再回来
策略二:最快的和次快的一起过河,最快的回来,然后最慢的和次慢的一起过河,次快的回来,然后最快和次快的一起过河。
可以表示为 T1 T2 T3 T4(T1<T2<T3<T4),对应的过河顺序见下图
可以选用哪种策略取决于时间差t=T1+T3-2T2的大小,如果t<0,说明方法一用时少,如果t>0说明方法二用时少
对于多个人则每次过河的顺序取决于两个决策方法哪个用时比较少,以四个人为单位,按上述用时,比较哪个更小
例如对于6个人
方法一全部采用策略一
方法二既采用策略一也采用策略二
方法三全部采用策略二
每两个来回可以送过去两个人,选择哪一种策略重点是min(a[0]*2+a[n-1]+a[n-2],a[0]+a[1]*2+a[n-1])
实现代码
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,i,k,sum=0;
int a[1010];
cin>>k;
while(k--){
sum=0;
cin>>n;
for(i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
while(n>3){
sum+=min(a[0]*2+a[n-1]+a[n-2],a[0]+a[1]*2+a[n-1]);
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];
cout<<sum<<endl;
}
return 0;
}