zoj3541、hdu4053 (区间DP+逆向思维好题)

The Last Puzzle
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1103 Accepted Submission(s): 112
Special Judge

Problem Description
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.

Author
WANG, Yelei

Source
2011 Asia Dalian Regional Contest

Recommend
lcy | We have carefully selected several similar problems for you: 4056 4057 4059 4052 4054

[题目来源]http://acm.hdu.edu.cn/showproblem.php?pid=4053

题意:在x轴上有n盏灯,人初始值位于0,告诉每盏灯的照明时间ti(从开始按的时候算起),并且人的移动速度为每单位一秒,求一组使得所有灯都亮着的按灯方式,如果不可能,输出Mission Impossible。

题解:
第一眼看是贪心,按照明时间排序,但还有距离的影响,还有方向的影响,舍弃。
等等想到方向,有两种方向,又看出是区间dp,用dp【i】【j】【0/1】表示把区间i~j都按了的最大的剩余时间,但这样区间内的灯很有可能随着你继续按别的灯,灭了,你还得回去按,于是各种骚操作都不对。
后经艾教讲题解,才明白要逆向思维想,dp【i】【j】【0/1】表示其他的都按了,并且将要把此区间按完的最短时间,如果他比t【i-1】时间短,说明上一步可以是由i-1转移来的,同理如果满足情况,也可能从j+1来,但注意,当前在0/1不同时,所转移时加的距离也不同,如果上一步不能从i-1来或j+1来,则此区间变为正无穷,之后在注意用路径保存,下一步是走的哪里,i~j区间的左侧还是右侧,这是p【i】【j】【0/1】的作用。

附AC代码(zoj能过,hdu原题却不知为何过不了,吐槽下spj)

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=205;
const int inf=0x3f3f3f;
int n,t[maxn],d[maxn],dp[maxn][maxn][2],p[maxn][maxn][2],nxt,l,r,le,re;
int main()
{
    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));
        memset(p,0,sizeof(p));
        for(int len=2;len<=n;len++)
        for(int i=1;i<=n-len+1;i++)
        {
            int j=i+len-1;
            le=dp[i+1][j][0]+d[i+1]-d[i];
            re=dp[i+1][j][1]+d[j]-d[i];
            if(le<=re)
            {
                dp[i][j][0]=le;
                p[i][j][0]=0;
            }
            else 
            {
                dp[i][j][0]=re;
                p[i][j][0]=1;
            }
            if(t[i]<=dp[i][j][0]) 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)
            {
                dp[i][j][1]=le;
                p[i][j][1]=0;
            }
            else 
            {
                dp[i][j][1]=re;
                p[i][j][1]=1;
            }
            if(t[j]<=dp[i][j][1]) dp[i][j][1]=inf;
        }
        if(dp[1][n][0]<inf)
        {
            nxt=p[1][n][0];
            printf("1");
            l=2,r=n;
        }
        else if(dp[1][n][1]<inf)
        {
            nxt=p[1][n][1];
            printf("%d",n);
            l=1;r=n-1;
        }
        else 
        {
            puts("Mission Impossible");
            continue;
        }
        while(l<=r)
        {
            if(nxt==0)
            {
                nxt=p[l][r][0];
                printf(" %d",l);
                l++;
            }
            else 
            {
                nxt=p[l][r][1];
                printf(" %d",r);
                r--;
            }
        }
        printf("\n");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42618295/article/details/81749626