习题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\n",ans); else printf("No solution\n"); } return 0; }