贪心算法:小船过河问题
题意:N个人过河,船每次只能坐两个人,船载每个人过河的所需时间不同t[i],每次过河的时间为船上的人的较慢的那个,问最快的过河时间。(船划过去要有一个人划回来)
最优选择:
先将所有人过河所需的时间按照升序排序考虑把单独过河所需要时间最多的两个旅行者送到对岸去,有两种方式:
1.最快的和次快的过河,然后最快的将船划回来;次慢的和最慢的过河,然后次快的将船划回来,时间:t[0]+2t[1]+t[n-1];
2.最快的和最慢的过河,然后最快的将船划回来,最快的和次慢的过河,然后最快的将船划回来,时间:2t[0]+t[n-2]+t[n-1]。
上述分析存在于至少四个人的时候,少于三个人情况,我们单独讨论一下就好。
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int N=1e3+5;
int t[N];
int main()
{
int T,n;
cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;i++){
cin>>t[i];
}
sort(t,t+n);//排序
int sum=0,ks1,ks2;
while(n>3){//条件选取
ks1=t[0]+2*t[1]+t[n-1];
ks2=t[n-1]+2*t[0]+t[n-2];//情况列举
if(ks1>ks2){
sum+=ks2;
}else{
sum+=ks1;
}
n-=2;
}
if(n==3){//边界讨论
sum+=(t[0]+t[1]+t[2]);
}else if(n==2){
sum+=t[1];
}else{
sum+=t[0];
}
cout<<sum<<endl
return 0;
}