1 4 1 2 5 10Sample Output
17
题目就和曾经在某些数学问题差不多,讲的是:
有N个人想过河,但很不巧他们只有一艘船,然而每次可以过去两个人,但是得派对岸的其中一个人把船再开回来。
讲一下我错误的思路(可能是个通病):
我一开始想,每次过去两个人,再由一人开船回来,那岂不是每次去一个最快的带上一个河这岸最慢的过去不就可以了吗?但事实并非如此,我们发现这和题目给我们的例子答案不相吻合,得到的是19,显然不正确。
那么接下来讲一个正解,其中也会给出证明:
当岸这头有许多人的时候,我们得想法设法的尽快把人弄到对岸,如果这次去河对岸的是这些人中最快的两个(耗时分别为a,b),然后再将a送回,把最慢的两个人(耗时分别为x,y(x<y))送到对岸,并由b开船回来——此时的用时是a+2b+y
按照之前我错误的做法,把两个最慢的人送到河对岸得到的时间为2a+x+y
那么,我们对两个式子进行比较:2a+x+y>a+2b+y时,a+x>2b那么意味着我之前的思路只在“a+x>2b”这样的条件下才成立,而不成立的时候却符合后面补充的算法。
那么我们可以用个递归解决这类问题:
当N>=4的时候:
while(n>=4)
{
int t1=2*a[0]+a[n-1]+a[n-2];
int t2=2*a[1]+a[0]+a[n-1];
t+=min(t1, t2);
n-=2;
}
接下来处理N<=3就显得简单了:
N==1或者N==2的时候,t+=a[1]。
N==3的时候,就是简单的由最快的人将那两个人分别送过去这么简单了。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <limits>
#include <algorithm>
using namespace std;
int N;
int a[1005];
int t;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
for(int i=0; i<N; i++)
{
scanf("%d",&a[i]);
}
if(N<=2)
{
printf("%d\n",a[N-1]);
continue;
}
t=a[1];
sort(a, a+N);
int n=N;
while(n>=4)
{
int t1=2*a[0]+a[n-1]+a[n-2];
int t2=2*a[1]+a[0]+a[n-1];
t+=min(t1, t2);
n-=2;
}
if(n==3) t+=(a[2]+a[0]);
printf("%d\n",t);
}
return 0;
}