Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 10787 | Accepted: 4064 |
Description
Input
Output
Sample Input
1 4 1 2 5 10
Sample Output
17
题目大意
有n个人准备过河,他们只有一只船,这只船每次只能通过坐不超过2人(0,1,2人都可以),每个人都有不同的划船速度;同一组过河的人的速度是由较慢的速度来确定。你的任务是确定一个策略,最大限度的减少他们过河的时间(是他们最快的过河).
第一行是输入一个整数T(1<=T<=20)代表测试的数据组数.
每一组第一行输入一个数据n(n<=1000),代表过河的人数.下面一行有n个整数分别代表,n个人划船的速度.
我的想法.
现在用C[i]来存放存放第i个人划船速度.cost来存放全部n个人过河所用的时间.(cost初始值为0)
现在为了方便计算讲C[],数组安速度由小到大排序
1.如果只有一个人,
cost=C[1];
2.如果只有两个人
cost=C[2];(因为已经排序C[2]>C[1])
2.如果有三个人
一定会有一个人会划船两次(因为船一次不能白所有的人全部载过河,要载其他的人必须要有人把船划回来)
现在假设
节省时间的方法就是让过河用时间最少的划两次船,
假如有
3
2 3 5
用时间为2,用时间3的一起过河,用时间为2的再回来,用时间为2与用时间为5的在过去,
所用时间为2+3+5=10
因此如果是三个人cost=C[1]+C[2]+C[3];
如果是四个人,注意看这种情况是比较普遍的.
假设用时间分别是a,b,x,y
我们可以枚举所有的情况,
最后会发现在众多情况中解一直时出现在这两种情况之间.
1.a是用时最短的.那麽可以让a分四次讲这四个人带到对岸所用时间为.
b+a+c+a+d,(分别是带b过河,划船回来,带c过河,划船回来,带d过河不用划船会来因为没有人要过来了);
2.现将a和b划船到对岸,然后a回来,然后x,y划船到对岸然后b回来然后ab一起过和,
时间为 b+a+y+b+b
1.考虑了划船快的人划的次数最多,
2.考虑了划的满的人尽量少占用化的快的人的时间.
然后在者两种方案中考虑考虑一种较优的方案.四个人可以用最短的时间过河.
如果同样的是四个人只是讲两个较慢的,送到对岸,剩下的人就可以用两个人的情况判断。
1.cost=x+a+y+a
2.cost=b+a+y+b
然后只剩下a,b
他们划船用时间为b.
根据上述情况我们都可以把超过两个三个人的情况处理为2或者三个人的情况.
如果有n个人n>3,n%2==1,就可已通过有限次数最优的方式,将n-3个人送到对岸此时剩下的三个人按三个人的情况来算(为了方便每伦讲靠近最后的2个人,有第一个,与
第二个,送完之后一二没在没有过河,再用他们松下一波人),最后剩余的是1,2,3号
偶数的话最后剩余1,2号.
然后安三个以内的人方法讲剩余的人送过去.
具体如下:
Source Code
Problem: 1700
Memory: 360K Time: 0MS
Language: GCC Result: Accepted
Source Code
#include <stdio.h>
#include <stdlib.h>
#define maxn 5005
int mycmp(const void * pa,const void * pb){
return *((int *)pa) > *((int *)pb);
}
void print(int C[],int n){
int i;
for(i=1;i<=n;i++){
printf("%d ",C[i]);
}
printf("\n");
}
int main(){
int C[maxn]={0},n,i,m;
scanf("%d",&m);
while(m-- > 0){
scanf("%d",&n);
int cost=0;
for(i=1;i<=n;i++){
scanf("%d",&C[i]);
}
qsort(C+1,n,sizeof(C[0]),mycmp);
while(n>3){
if(C[2]+C[2]<C[1]+C[n-1]){
cost+=(C[2]+C[2]+C[1]+C[n]);
}else{
cost+=(C[1]+C[1]+C[n-1]+C[n]);
}
n-=2;
}
if(n<3) cost+=C[n];
else cost+=C[1]+C[2]+C[3];
printf("%d\n",cost);
}
return 0;
}