ZOJ 3541 - The Last Puzzle(区间dp)

来源:互联网 发布:镇江淘宝模特兼职招聘 编辑:程序博客网 时间:2024/06/08 17:09

The Last Puzzle

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 T1, T2, …, 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 D1, D2, …, 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

2
4 3
0 3
2
3 3
0 3
4
5 200 1 2
0 1 2 3

Sample Output

1 2
Mission Impossible
1 2 4 3

Hint

In the second sample, no matter which button the hero pressed first, the button would always pop up before he press the other button. So there is no way to make all the button pressed down.

题意:有N盏灯排成一条直线,每一盏灯有一个时间T,表示如果这盏灯打开T时间后,后自动灭掉,每盏距离1的距离为di,问能否有个时刻所有的灯都是亮的,起点随意
Zoj 3541 The Last Puzzle (dp) - 2011 ACM-ICPC Dalian Regional Contest Problem C
思路:dp[i][j] 表示把开关i到j都按下需要的时间,可以从任意一个开始。
现在要证明一个结论:对于区间[i,j]如果有解,那么最优解(即所花时间最短)的方案的起始点一定是在区间的端点(左端点或右端点)。

文字证明:

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

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef long long LL;const int maxn=210;const int maxm=1010;const int MOD=1e9+7;const int INF=0x3f3f3f3f;int N,t[maxn],d[maxn];int dp[maxn][maxn][2],path[maxn][maxn][2];int main(){    while(scanf("%d",&N)!=EOF)    {        for(int i=1;i<=N;i++)scanf("%d",&t[i]);        for(int j=1;j<=N;j++)scanf("%d",&d[j]);        memset(dp,0,sizeof(dp));        for(int l=2;l<=N;l++)        {            for(int i=1;i+l-1<=N;i++)            {                int j=i+l-1;                if(dp[i+1][j][0]+d[i+1]-d[i]<dp[i+1][j][1]+d[j]-d[i])                {                    dp[i][j][0]=dp[i+1][j][0]+d[i+1]-d[i];                    path[i][j][0]=0;                }                else                {                    dp[i][j][0]=dp[i+1][j][1]+d[j]-d[i];                    path[i][j][0]=1;                }                if(dp[i][j][0]>=t[i]||dp[i][j][0]>INF)                    dp[i][j][0]=INF;                if(dp[i][j-1][0]+d[j]-d[i]<dp[i][j-1][1]+d[j]-d[j-1])                {                    dp[i][j][1]=dp[i][j-1][0]+d[j]-d[i];                    path[i][j][1]=0;                }                else                {                    dp[i][j][1]=dp[i][j-1][1]+d[j]-d[j-1];                    path[i][j][1]=1;                }                if(dp[i][j][1]>=t[j]||dp[i][j][1]>INF)                    dp[i][j][1]=INF;            }        }        int l,r,m;        if(dp[1][N][0]<INF)        {            l=2,r=N;            m=path[1][N][0];            printf("1");        }        else if(dp[1][N][1]<INF)        {            l=1,r=N-1;            m=path[1][N][1];            printf("%d",N);        }        else        {            printf("Mission Impossible\n");            continue;        }        while(l<=r)        {            if(m==0)            {                printf(" %d",l);                m=path[l][r][m];                l++;            }            else if(m==1)            {                printf(" %d",r);                m=path[l][r][m];                r--;            }        }        printf("\n");    }    return 0;}
0 0
原创粉丝点击