ZOJ3541与时间相关的区间dp+记录路径
2017-07-29 20:15
387 查看
与时间相关的区间dp+记录路径
题意:一个英雄深陷龙穴,现在有一个门,不过想把门打开需要把门上的按钮全部在同一时间都是按下状态,按钮排成一排:每一个按钮都有两个属性:
按下的状态能维持ai 个单位时间
按钮之间有距离,具体就是离第一个按钮的距离
问:英雄是否能使得全部 的按钮在同一时间都保持被按下的状态?如果可以请输出按按钮的顺序,如果不能输出一个字符串。
思路:
先普及一个知识:一个区间如果想遍历完,并且是时间最短,自然就是只能从两端开始,这样会把时间最短。
对于本题来说:遍历所有按钮的时间越短就会使得被按下按钮维持的时间更充裕
所以:对于一排按钮有两种可能
从左到右按下
从右到左按下
定义:dp[i][j][0] 表示从第i到第j的所有按钮被按下的最短时间,第三维0表示第i到第j是从做到右
dp[i][j][1] 表示从第i到第j的所有按钮被按下的最短时间,第三维1表示第i到第j是从右到左。
那么只需要遍历区间就行了,对于每一次判断从右还是从左只需单独比较就行了。
不过这道题最有意思还有一点就是:保存路径,其巧妙程度值得推敲
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 1005; const int INF = 0x3f3f3f3f; int n; int a[maxn],b[maxn]; int dp[maxn][maxn][2]; int path[maxn][maxn][2]; int main(int argc, char const *argv[]) { //freopen("in.txt","r",stdin); while(scanf("%d",&n) != EOF) { memset(dp,0,sizeof(dp)); memset(path,0,sizeof(path)); for(int i = 1;i <= n; i++) { scanf("%d",&a[i]); } for(int j = 1;j <= n; j++) { scanf("%d",&b[j]); } for(int l = 2;l <= n; l++) { for(int i = 1;i+l-1 <= n; i++) { int j = i + l - 1; /*从左向右*/ int temp1 = dp[i+1][j][0] + b[i+1] - b[i]; int temp2 = dp[i+1][j][1] + b[j] - b[i]; if(temp1 <= temp2) { dp[i][j][0] = temp1; path[i][j][0] = 0; /*定义为i到j从左走之后下一次走从左向右为0*/ } else { dp[i][j][0] = temp2; path[i][j][0] = 1; /*定义为i到j从左走之后下一次走从右向左为1*/ } if(a[i] <= dp[i][j][0]) /*若低于i自动上升的是时间则为不可达*/ dp[i][j][0] = INF; /*从右往左*/ temp1 = dp[i][j-1][1] + b[j] - b[j-1]; temp2 = dp[i][j-1][0] + b[j] - b[i]; if(temp1 >= temp2) { dp[i][j][1] = temp2; path[i][j][1] = 0; } else { dp[i][j][1] e29c = temp1; path[i][j][1] = 1; } if(a[j] <= dp[i][j][1]) dp[i][j][1] = INF; } } int l,r,temp; if(dp[1] [0] < INF) { temp = path[1] [0]; l = 2,r = n; printf("1"); } else if(dp[1] [1] < INF) { temp = path[1] [1]; l = 1,r = n - 1; printf("%d",n); } else { printf("Mission Impossible\n"); continue; } while(l <= r) { if(temp == 0) { temp = path[l][r][0]; printf(" %d",l++); } else { temp = path[l][r][1]; printf(" %d",r--); } } printf("\n"); } return 0; }
相关文章推荐
- POJ 1142 Brackets Sequence(区间dp,记录路径,还原括号匹配)
- poj1141 Brackets Sequence(区间dp记录路径问题)
- POJ 1141 Brackets Sequence(区间DP记录路径)
- ural1183&&poj1141 Brackets Sequence(区间DP+记录路径)
- poj 1141 (区间dp记录路径问题)
- poj1141(区间dp+记录路径)
- POJ 1141 Brackets Sequence (区间dp 记录路径)
- 【URAL 1635】Mnemonics and Palindromes(区间DP+记录路径)
- poj 1141 Brackets Sequence(区间DP记录路径)
- poj 1141 Brackets Sequence 【区间DP+路径记录】
- (常复习)poj 1015 dp+记录dp路径+转变最优子结构+区间映射
- POJ 1141Brackets Sequence (区间dp记录路径)
- poj1141Brackets Sequence【区间dp+路径记录】
- HDU 1160 FatMouse's Speed 最长上升子序列及记录路径DP
- hdu1074(状态压缩,DP,记录路径)
- [CF792C] Divide by Three(dp,记录路径)
- codeforces #436 - E. Fire (记录路径dp)
- POJ 2111 DP+记录路径
- Codeforces Round #436 (Div. 2) E. Fire(dp 记录路径)
- Codeforces 792C Divide by Three【Dp+记录路径】