题目描述
几个人过河,每次过两人一人回,速度由慢者决定,问过河所需最短时间。
输入格式
输入 t 组数据,每组数据第 1 行输入 n;
第 2 行输入 n 个数,表示每个人过河的时间。
输出格式
输出 t 行数据,每行 1 个数,表示每组过河最少时间。
输入输出样例
输入数据 1
1
4
1 2 5 10
输出数据 1
17
思路:
用贪心
我们把运两个人到对岸的时间作为比较当前(因为是贪心,所以只比较当前最优,不知道的读者可以去查一下贪心)最优方法的标准,通过题目分析可知,运两个人有两种可能最优的方法,一是用最快的运最慢的,其次是次慢的;为什么不从次快开始运呢,这其实只是作者的小习惯,不过从次快开始也是可以的。如果从次快开始应该把sort()改成从大到小就行了,但可能还要改一些地方,这里只是稍稍说说。第二种方法是先把最快与次快的先送过去,再让最快把船送回,然后最快下船,再把最慢与次慢也送过去(之所以这样是因为次慢与最慢一起走只用花最慢渡河的时间就行了,用最快一个一个送太久),然后次快送回船。其实最快与次快的作用就是送船。最慢与次慢送船的话太久了。然后我们统计两种方法的时间,把sum加上两种方法的时间的最小值就可以了。这道题的难点其实就是贪心策略,是s+两种方法的时间的最小值,代码很简单。还有一点重复,上述所说的方法只是指运两个人到对岸的方法。
代码:
#include<bits/stdc++.h>
using namespace std;
long long a[200000010];
int main(){
long long t;
cin>>t;
for(long long i=1;i<=t;i++){
long long n;
cin>>n;
for(long long j=1;j<=n;j++){
cin>>a[j];
}
if(n>1){//这里要特判,不然n==1什么都不输出
sort(a+1,a+n+1);
long long s=0;
while(n>3){
s+=min(a[2]+a[1]+a[n]+a[2],a[n]+a[1]+a[n-1]+a[1]);
n-=2;
}
if(n==3){
s+=a[2]+a[1]+a[3];
}else{
s+=a[2];
}
cout<<s<<endl;
}else{
cout<<a[1]<<endl;
}
}
return 0;
}