有n个人要过一条河,每个人过河都需要一个时间,有一艘船,每次过河只能最多装两个人。两个人划船过河所需的时间都取决于过河时间长的那个人。比如,A,B两人过河所需时间分别为a,b,那么,他们成一条船过河所需的时间为:max{a,b}。现在让你安排一个过河方案,让所有人用最短的时间全部过河。
输入:第一行给出人的数量
接下来的1行给出每个人的速度
4
1 2 5 10
输出
最短时间
17
算法分析
设其中四人为a、b、c、d,并且所需时间a<b<c<d
那么,现在想让c、d过河,然后再让船回到过河前的位置,准备好继续送其他的人过河。有两种运载方式:
1.过河顺序为:ac、a、ad、a 时间消耗:t 1 =2a+c+d
2.过河顺序为:ab、a(b)、cd、b(a) 时间消耗:t 2 =a+2b+d
t 1 −t 2 =a+c−2b
选择两种方案的哪一种,和a+c−2b 的值有关。
设定n个人过河的贪心策略为:
在要过河人数n≥4的时候,先用上述两种方法中较好的一个,把最大的两个送过河(用过河时间最少的人作为上述方法的a,第二少的作为上述方法的b)。
然后该问题就变成了:寻找把剩下的n-2个人送过河的最优策略。
反复执行此策略,直到
n=2时,显然两个人直接过去就行了,
n=3时,用最小的分别把两个送过去为最优(三个人过河,显然就是:过去两个人,回来一个,在过去两个,两次过去两个的花费分别为:b、c,那这个回来的人,应该是a才能最快,也就是让a分别送b、c。)
#include<iostream>
#include<algorithm>
using namespace std;
int x[1100];
int min(int a, int b ){
if(a>=b)return b;
return a;
}
int main(){
int N;
cin>>N;
for(int i=1;i<=N;++i)
cin>>x[i];
sort(x+1,x+N+1);
int num=0;
while(N>3){
num+=min((x[1]+x[2]+x[N]+x[2]),(x[1]+x[N]+x[1]+x[N-1]));
N-=2;
}
if(N==2)
num+=x[2];
else if(N==3)
num+=x[1]+x[2]+x[3];
else if(N==1)
num+=x[1];
cout<<num;
return 0;
}