Problem Address:http://poj.org/problem?id=1700
【思路】
dp是O(n)的复杂度。
从后往前推,对于每一个人,
可以单独一个人过去(此时需要用耗时最小的那个人一起过去,之后那个人自己回来),
或者和前一个人一起过去(此时需要耗时最小的两个人一起过去,然后最小那个过来,然后预定好的两个人过去,之后第二小的那个人过来),
取其小者。
dp[i] = min(dp[i+1]+num[i]+num[0], dp[i+2]+num[1]*2+num[0]+max(num[i],num[i+1]))。
最后剩下两个人,则取其时间大者。
注意n=1、n=2的情况。
【代码】
#include <iostream>
#include <algorithm>
using namespace std;
#define max(a,b) ((a)>=(b)?(a):(b))
#define min(a,b) ((a)<=(b)?(a):(b))
const int maxn = 1000;
int num[maxn+5];
int dp[maxn+5];
int main()
{
int t;
int n;
int i;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for (i=0; i<n; i++)
scanf("%d", &num[i]);
if (n==1)
{
printf("%d\n", num[0]);
continue;
}
else if (n==2)
{
printf("%d\n", max(num[0], num[1]));
continue;
}
sort(num, num+n);
memset(dp, 0, sizeof(dp));
for (i=n-1; i>=2; i--)
{
dp[i] = min(dp[i+1]+num[i]+num[0], dp[i+2]+num[1]*2+num[0]+max(num[i],num[i+1]));
}
printf("%d\n", dp[2]+num[1]);
}
return 0;
}