1232:Crossing River
【题目描述】
几个人过河,每次过两人一人回,速度由慢者决定,问过河所需最短时间。
【输入】
输入t组数据,每组数据第1行输入n,第2行输入n个数,表示每个人过河的时间。
【输出】
输出t行数据,每行1个数,表示每组过河最少时间。
【输入样例】
1
4
1 2 5 10
【输出样例】
17
个人思路:
一步步分解。
每组操作都将剩下的人中最慢和次慢的人(贪心)送过去。
操作中有两种方法:(都是想办法让剩下人中n和n-1过去)
第一种:最快的人1带动慢的n和n-1,这样运过n和n-1共需要A1+An+A(n-1)+A1时间。
第二种:最快的1先和次快的2过去,然后最快的1回来,让n和n-1一起过去,然后让刚开始去的2回来,时间为A2+A1+An+A2。
看一下这两种哪一种时间小,也就是说比较 A(n-1)+A1与2*A2的关系。
总之,每组操作之后,在岸对面留下的都是慢的人,因为不要让他们回来,所以回来的都是快的。
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
//从过程入手考虑
//有两种(都是想办法让n和n-1过去):第一种最快的人1带动慢的n和n-1,这样运过n和n-1共需要A1+An+A(n-1)+A1时间。
//第二种,最快的1先和次快的2过去,然后最快的1回来,让n和n-1一起过去,然后让刚开始去的2回来,时间为A2+A1+An+A2。
//看一下这两种哪一种时间,也就是说比较 A(n-1)+A1与2*A2的关系。
//总之,每组操作之后,在岸对面留下的都是慢的人
int main()
{
int t;
cin>>t;
int a[10001];
for(int i=1;i<=t;i++)//t个测试
{
int n;
cin>>n;
memset(a,0,sizeof(a));
for(int j=1;j<=n;j++)
cin>>a[j];
sort(a+1,a+1+n);//排序
int sheng=n;//剩下的人
long long int sum=0;//总时间
while(sheng!=2&&sheng!=3)//分析一下结束的时候
{
sum+=min(2*a[2],a[sheng-1]+a[1])+a[1]+a[sheng];
sheng=sheng-2;//每组操作运过剩下的最慢和次慢
}
if(sheng==2)
sum+=a[2];
else if(sheng==3)//当只剩下3个的时候,只能选用第一种方法
sum+=a[sheng]+a[sheng-1]+a[1];
cout<<sum<<endl;
}
return 0;
}