Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13982 | Accepted: 5349 |
Description
Input
Output
Sample Input
1 4 1 2 5 10
Sample Output
17
引用来自http://www.w2bc.com/Article/18634的思路,按照自己的习惯做了些修改:
贪心思想(一般都是先排序)
每次从此岸到对岸移动的两个人要么这两个人中有一个是时间最快的那个人,要么这两个人到达对岸后再也不回来。即:要么最快+最慢(最快回来换人),要么最慢+次慢(不回来)。
1.对N个人过河时间从小到大排序。p[i];
2.分情况讨论:
⑴当n = 1,直接过河。sum = p[1]
(2)当n = 2,直接过河。 sum = p[2]
(3)当n = 3,无论怎么过河, sum = p[1] + p[2] + p[3]
(4)当n >= 4,设从小到大排序后位a,b,……,c,d,大于4个人,a,b是最小的两个人,c,d是最大的两个人,目标就是把最大的两个人送过去。就要牺牲最小的。
用最小的来送:A=d + a + c + a = 2a + c + d = 2*p[1] + p[end-1] + p[end];(a,d过去,a回来,a,c过去,a回来)
两小送两大:B= b + b + d + a = a + 2b + d = 2*p[1] + p[end-1] + p[end];(a,b过去,b回来,c,d过去,a回来)
循环:sum = min(A,B),直到n <= 3 时候结束。
#include<cstdio>
#include<algorithm>
using namespace std;
int p[1003];
int min(int a,int b) {return a<b?a:b;}
int time_sum(const int p[],int end)
{
if(end == 3) return p[1]+p[2]+p[3];
if(end == 2) return p[2];
if(end == 1) return p[1];
int time_1= 2*p[1] + p[end-1] + p[end] + time_sum(p,end-2);
int time_2= 2*p[2] + p[end] + p[1] + time_sum(p,end-2);
return min(time_1,time_2);
}
int main()
{
int t,n,time;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
sort(p+1,p+n+1);
if(n == 1){
time=p[1];
}
else if(n == 2){
time=p[2];
}
else if(n == 3){
time=p[1]+p[2]+p[3];
}
else if(n >= 4){
time=time_sum(p,n);
}
printf("%d\n",time);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
int p[1003];
int min(int a,int b) {return a<b?a:b;}
int main()
{
int t,n,time;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
sort(p+1,p+n+1);
if(n == 1){
time=p[1];
}
else if(n == 2){
time=p[2];
}
else if(n == 3){
time=p[1]+p[2]+p[3];
}
else if(n >= 4){
time=0;
int end=n;
while(end >= 4){
time+=min( 2*p[1] + p[end-1] + p[end] , 2*p[2] + p[end] + p[1] );
end-=2;
}
if(end == 3) time+=p[1]+p[2]+p[3];
else if(end == 2) time+=p[2];
else if(end == 3) time+=p[1];
}
printf("%d\n",time);
}
}