• HDU 4053 or ZOJ 3541 The Last Puzzle【区间dp】【经典题】


    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

    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(1<=n<=200)个开关,开关i的属性d[i]表示它到最左端开关的距离,t[i]表示它被按下t[i]秒后又自动弹出。
    求一个按开关的顺序,使得某时刻所有的开关都被按下。可以从任意一个开关开始,而且手移动的速度是每秒钟一个单位长度,
    按开关所用的时间忽略不计。


    题解:

    dp[i][j][0]表示从i开始到j按完所需要的最短时间

    dp[i][j][1]表示从j开始到i按完所需要的最短时间

    因为dp[i][j][0]从i开始,所以上一状态为dp[i+1][j][0|1]加上i到i+1或i到j的距离,同理dp[i][j][1]为dp[i][j-1][0|1]加上j到i或j到j-1的距离。


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define INF 0x3f3f3f3f
    #define ms(x,y) memset(x,y,sizeof(x))
    using namespace std;
    
    const double pi = acos(-1);
    const double eps = 1e-8;
    const int maxn = 210;
    
    int dp[maxn][maxn][2], n, t[maxn], d[maxn], Next[maxn][maxn][2];
    
    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);
    		ms(dp, 0);
    		for (int l = 2; l <= n; l++) //枚举区间长度
    		{
    			for (int i = 1; i + l - 1 <= n; i++) //枚举区间左端点
    			{
    				int j = i + l - 1;	//区间右端点
    
    				//计算dp[i][j][0],判断左端点i到其上一步递归的距离
    				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];
    					Next[i][j][0] = 0;
    				}
    				else
    				{
    					dp[i][j][0] = dp[i + 1][j][1] + d[j] - d[i];
    					Next[i][j][0] = 1;
    				}
    				if (dp[i][j][0] >= t[i])	//判断是否可行,当前按下i
    				{
    					dp[i][j][0] = INF;
    				}
    
    				//计算dp[i][j][1],判断右端点j到其上一步递归的距离
    				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];
    					Next[i][j][1] = 0;
    				}
    				else
    				{
    					dp[i][j][1] = dp[i][j - 1][1] + d[j] - d[j - 1];
    					Next[i][j][1] = 1;
    				}
    				if (dp[i][j][1] >= t[j])	//判断是否可行,当前按下j
    				{
    					dp[i][j][1] = INF;
    				}
    			}
    		}
    		int l, r, m;
    		if (dp[1][n][0] < INF)
    		{
    			l = 2;
    			r = n;
    			m = Next[1][n][0];
    			printf("1");
    		}
    		else if (dp[1][n][1] < INF)
    		{
    			l = 1;
    			r = n - 1;
    			m = Next[1][n][1];
    			printf("%d", n);
    		}
    		else
    		{
    			printf("Mission Impossible
    ");
    			continue;
    		}
    		while (l <= r)
    		{
    			if (m == 0)	//下一步从左走
    			{
    				printf(" %d", l);
    				m = Next[l][r][0];
    				l++;
    			}
    			else
    			{
    				printf(" %d", r);
    				m = Next[l][r][1];
    				r--;
    			}
    		}
    		printf("
    ");
    	}
    }
    
    




    Fighting~
  • 相关阅读:
    css+javascript 仿outlook滑动菜单效果代码
    闭包
    AJAX式多数据源及节点异步加载树_meetrice
    CSS圆角边框表格
    Editplus 3.0 开发ext 教程
    IE右键快速转载到博客
    自已扩展EXT组件(Extending Ext Components)
    Ext程序规划入门
    EXT2联动选框 (Linked Combos Tutorial for Ext 2)
    EXT snippets 笔记
  • 原文地址:https://www.cnblogs.com/Archger/p/12774742.html
Copyright © 2020-2023  润新知