POJ1700 Crossing River DP

来源:互联网 发布:js 画弧线 编辑:程序博客网 时间:2024/05/16 00:40

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;}