习题9-8 Uva1632

题意:

给你n个宝藏,然后给出他们的位置a[i]以及存在时间tim[i],如果能全部拿完,求出最短时间;

否则输出No solution


思路:

对于一段区间[i,j],你取完之后肯定是在最左端或者最右端,因为如果最后你停在中间位置,你始终会先到左右,所以并不能是最优解。

所以我们dp[i][j][0]表示拿完[i,j]后停在左端,dp[i][j][1]表示拿完[i,j]后停在右端

然后利用公式从小区间往大区间递推即可


Orz:

最开始递推方程不简洁,初始化数组时花费了很多时间,TL;而完全可以不初始化的

判断条件写成>tim[i],然而在tim[i]时宝藏已经消失了,所以应该是 >=


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;
const int maxn = 10005;
const int INF = 0x3f3f3f3f;
int a[maxn];
int dp[maxn][maxn][2];
int tim[maxn];

int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",a+i,tim+i);
        }

        for(int l = 1; l <= n; l++)
        {
            for(int i = 1; i+l <= n; i++)
            {
                int j = i + l;
                dp[i][j][0] = min(dp[i+1][j][0] + a[i+1]-a[i],dp[i+1][j][1] + a[j] - a[i]);
                if(dp[i][j][0] >= tim[i])
                    dp[i][j][0] = INF;
                dp[i][j][1] = min(dp[i][j-1][1] + a[j] - a[j-1],dp[i][j-1][0] + a[j] - a[i]);
                if(dp[i][j][1] >= tim[j])
                    dp[i][j][1] = INF;
            }
        }
        int ans = min(dp[1][n][0],dp[1][n][1]);
        if(ans != INF)
            printf("%d
",ans);
        else
            printf("No solution
");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/Przz/p/5409678.html