ZOJ 3541-The Last Puzzle(区间DP)

来源:互联网 发布:三菱fx3ga编程手册 编辑:程序博客网 时间:2024/06/16 15:31

题目链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4496

The Last Puzzle

Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge



There is one last gate between the hero and the dragon. But opening the gate isn't an easy task.

There were n buttons list in a straight line in front of the gate and each with an integer on it. Like other puzzles the hero had solved before, if all buttons had been pressed down in any moment, the gate would open. So, in order to solve the puzzle, the hero must press all the button one by one.

 After some trials, the hero found that those buttons he had pressed down would pop up after a while before he could press all the buttons down. He soon realized that the integer on the button is the time when the button would automatic pop up after pressing it, in units of second. And he measured the distance between every button and the first button, in units of maximum distance the hero could reach per second. Even with this information, the hero could not figure out in what order he should press the buttons. So you talent programmers, are assigned to help him solve the puzzle.

To make the puzzle easier, assuming that the hero always took integral seconds to go from one button to another button and he took no time turnning around or pressing a button down. And the hero could begin from any button.

Input

The input file would contain multiple cases. Each case contains three lines. Process to the end of file.

The first line contains a single integer n(1 ≤ n ≤200), the number of buttons.

The second line contains n integers T1T2, ..., Tn, where Ti(1 ≤ Ti ≤ 1,000,000) is the time the ith button would automatic pop up after pressing it, in units of second.

The third line contains n integers D1D2, ..., Dn, where Di(1 ≤ Di ≤ 1,000,000) is the time hero needed to go between the ith button and the first button, in units of second. The sequence will be in ascending order and the first element is always 0.

Output

Output a single line containing n integers which is the sequence of button to press by the hero. If there are multiply sequences, anyone will do. If there is no way for the hero to solve the puzzle, just output "Mission Impossible"(without quote) in a single line.

Sample Input

24 30 323 30 345 200 1 20 1 2 3

Sample Output

1 2Mission Impossible1 2 4 3

题意:
一条直线上有n(1<=n<=200)个开关,开关i的属性d[i]表示它到最左端开关的距离,t[i]表示它被按下t[i]秒后又自动弹出。
求一个按开关的顺序,使得某时刻所有的开关都被按下。可以从任意一个开关开始,而且手移动的速度是每秒钟一个单位长度,
按开关所用的时间忽略不计。
题解:
dp[i][j] 表示把开关i到j都按下需要的时间,可以从任意一个开始。
现在要证明一个结论:对于区间[i,j]如果有解,那么最优解(即所花时间最短)的方案的起始点一定是在区间的端点(左端点或右端点)。

文字证明:

对于n<=2显然成立。

对于n>=3,假设起始点不是端点,而是中间的某个点,在按完一些按钮后必然会按一个端点按钮(此时另一个端点还没有被按下),
在按下第一个端点和按下另一个端点按钮过程中,必然要经过该区间内所有的点,其中有一些点已经在之前被按下,很显然,
这些点“晚按”比“早按”更优。所以,在端点被按下之前的所有按下操作都是多余的,浪费时间的,完全可以在端点按下之后再按。
(口述证明比较难懂,自己琢磨)
现在整个过程就能这样看了:开始从[1,n]区间取一个端点按下后,剩下一段连续的区间,再选取一个端点按下,还是剩下一段连续的区间...
现在就用
dp[i][j][0] 表示先按下区间[i,j]的左端点
dp[i][j][1] 表示先按下右端点


要求[1,n]就可以递归到求[1,1],[2,2]...[n,n],而dp[i,i]=0;

以上参考自:http://blog.csdn.net/morgan_xww/article/details/6844333


//区间DP, AC代码#include <stdio.h>#include <algorithm>#include <string.h>#define maxn 225#define inf 0x3f3f3f3fusing namespace std;int dp[maxn][maxn][2];int path[maxn][maxn][2];//dp[i][j][0]表示区间i~j从左边端点开始按 dp[][][1]表示从右边端点开始//path[i][j][k]表示与之对应的状态。int d[maxn], t[maxn];int main(){int n;while(scanf("%d", &n)!=EOF){for(int i=0; i<n; i++)scanf("%d", &t[i]);for(int i=0; i<n; i++)scanf("%d", &d[i]);memset(dp, 0, sizeof(dp));memset(path, 0, sizeof(path));for(int len=2; len<=n; len++)for(int i=0; i<n; i++){int j = i + len - 1;//处理左端点int le = dp[i+1][j][0] + d[i+1] - d[i];int re = dp[i+1][j][1] + d[j] - d[i];if(le < re){path[i][j][0] = 1; //从左端点来dp[i][j][0] = le;}else{path[i][j][0] = 0; //去右端点dp[i][j][0] = re;}if(t[i] <= dp[i][j][0] || dp[i][j][0]>=inf)dp[i][j][0] = inf;//处理右端点le = dp[i][j-1][0] + d[j] - d[i];re = dp[i][j-1][1] + d[j] - d[j-1];if(le < re){path[i][j][1] = 1; //去左端点dp[i][j][1] = le;}else{path[i][j][1] = 0; //从右端点dp[i][j][1] = re;}if(t[j] <= dp[i][j][1] || dp[i][j][1]>=inf)dp[i][j][1] = inf;}int r, l, va;if(dp[0][n-1][0]<inf){printf("1");l = 1, r = n-1;va = path[0][n-1][0];}elseif(dp[0][n-1][1]<inf){printf("%d", n);l = 0, r = n-2;va = path[0][n-1][1];}else{printf("Mission Impossible\n");continue;}while(l<=r){if(va==0){printf(" %d", r+1);va = path[l][r][1];r--;}else{printf(" %d", l+1);va = path[l][r][0];l++;}}printf("\n");}return 0;}


原创粉丝点击