区间dp - 全部按下一列石头

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.

 

题意:有一列石头,只有全部按下的时候才能打开大门,可以任意选择按下的起点,但是每个石头还有一个隔一段会弹起的时间,问是否存在一种方案可以打开大门。

思路分析:

  首先这个人如果可以成功打开石门的按下的方案一定是每次都是从左侧或右侧去按,不然你先中间按下一次,但是它的左侧或右侧还有没按的,这时如果再回去按,那么先按的中间的这个显然时间会变长,因此是不可取的。

  类似送外卖那个问题,dp[i][j][0]表示送完区间(i, j)后此人位于区间的左侧,dp[i][j][1]表示位于右侧,那么就可以得到处理完全部区间后最优的时间,但是在求的过程要判断一下当前扩展出来的区间的是否是满足题目要求的,同时记录一下路径,最后倒着往回想一下就可以了。

代码示例:

int n;
int t[205], d[205];
int dp[205][205][2];
int path[205][205][2];

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    
    while(~scanf("%d", &n)){
        for(int i = 1; i <= n; i++) scanf("%d", &t[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &d[i]);
                
        memset(dp, 0, sizeof(dp));
        for(int len = 2; len <= n; len++){
            for(int i = 1; i <= n; i++){
                int j = i+len-1;
                if (j > n) break;
                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 (t[i] <= dp[i][j][0]) dp[i][j][0] = inf;
                
                if (dp[i][j-1][1]+d[j]-d[j-1] <= dp[i][j-1][0]+d[j]-d[i]){
                    dp[i][j][1] = dp[i][j-1][1]+d[j]-d[j-1];
                    path[i][j][1] = 1;
                }
                else {
                    dp[i][j][1] = dp[i][j-1][0]+d[j]-d[i];
                    path[i][j][1] = 0;
                }
                if (t[j] <= dp[i][j][1]) dp[i][j][1] = inf;
            }
        }        
        
        int tem;
        int l = 1, r = n;
        if (dp[1][n][0] < inf){
            printf("1");
            tem = path[1][n][0];
            l++;
        }
        else if (dp[1][n][1] < inf){
            printf("%d", n);
            tem = path[1][n][1];
            r--;
        }
        else {printf("Mission Impossible\n"); continue;}
        
        while(l <= r){
            if (tem == 0){
                tem = path[l][r][0];
                printf(" %d", l++);
            }
            else{
                tem = path[l][r][1];
                printf(" %d", r--);
            }
        }
        printf("\n");
    }    
    return 0;
}

 

posted @ 2018-06-12 08:27  楼主好菜啊  阅读(220)  评论(0编辑  收藏  举报