动规-POJ-1661

http://poj.org/problem?id=1661

Help Jimmy

在同一竖直平面上,存在地面(高度为0,长度无限),以及若干个给定高度的水平平台(高度、左右端点给定)。

现有Jimmy从给定点(x, y)跳下,下落的速度恒为1单位距离/单位时间。但下落的距离不能超过给定的高度MAX,否则Jimmy就会摔死。

若Jimmy降落在某一个平台上,那么Jimmy可以选择从平台的左端点或者右端点继续跳下。

问:Jimmy到达地面的最短时间。

保证Jimmy一定有办法安全降落到地面。

保证没有重叠的平台。

若Jimmy恰好落在平台的左端点或者右端点,也算作Jimmy跳到这个平台上。

解题报告

思路

首先,可以把题设中的其实点和地面也抽象为平台加入平台数组中。

每个平台都有从左跳和从右跳两种选择,且跳之后的落点是确定的,跳之前的状态不影响跳之后的状态转移,没有后效性——动态规划。

首先将平台数组按高度排序。

随后建立数组dp[i][j]表示,Jimmy达到第i个平台的j端点时,需要的最短时间。

初始化dp[0][0] = dp[0][1] = 1(初始点时间花费为0)

从高到低遍历每个平台,枚举从平台左右端点跳下的情况.

假设从i平台的j端点跳下以后,能安全到达k平台,那么:

dp[k][0] = min(dp[k][0], dp[i][j] + 高度差 + 从k平台上的落点到0端点的时间花费)

dp[k][1] = min(dp[k][1], dp[i][j] + 高度差 + 从k平台上的落点到1端点的时间花费)

要注意,下落过程不能穿过平台,所以每个平台跳下过程最多从左右端点各转移一次。

当然,到达地面以后不需要跑到左右端点,所以要特判一下到达地面的情况。

最后输出min( dp[地面][0], dp[地面][1] )即可

代码

#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;

const int maxn = 1003;
const int INF = 20004;

struct Platform {
    int l, r, h;
    Platform(int _l = 0, int _r = 0, int _h = 0) : l(_l), r(_r), h(_h) {}
    bool operator<(const Platform &Right) const {
        return h > Right.h;
    }
} platform[maxn];

int n, t, cnt;
int stx, sty, maxh;
int top;

int dp[maxn][2];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> t;
    while (t--) {
        cin >> n >> stx >> sty >> maxh;
        cnt = 0;
        for (int i = 0; i < n; i++) {
            int l, r, h;
            cin >> l >> r >> h;
            if (h > sty || (h == sty && (stx < l || stx > r))) continue;
            platform[cnt++] = Platform(l, r, h);
        }
        platform[cnt++] = Platform(stx, stx, sty);
        platform[cnt++] = Platform(-INF, INF, 0);
        sort(platform, platform + cnt);
        memset(dp, 0x3f3f3f3f, sizeof(dp));
        dp[0][0] = dp[0][1] = 0;
        for (int i = 0; i < cnt - 1; i++) {
            bool flagl = false, flagr = false;
            for (int j = i + 1; j < cnt && platform[i].h - platform[j].h <= maxh; j++) {
                if(flagl && flagr) break;
                if (platform[i].l >= platform[j].l && platform[i].l <= platform[j].r && !flagl) {
                    dp[j][0] = min(dp[j][0], dp[i][0] + platform[i].h - platform[j].h + platform[i].l - platform[j].l);
                    dp[j][1] = min(dp[j][1], dp[i][0] + platform[i].h - platform[j].h + platform[j].r - platform[i].l);
                    if (j == cnt - 1) {
                        dp[j][0] = min(dp[j][0], dp[i][0] + platform[i].h - platform[j].h);
                        dp[j][1] = min(dp[j][1], dp[i][0] + platform[i].h - platform[j].h);
                    }
                    flagl = true;
                }
                if (platform[i].r >= platform[j].l && platform[i].r <= platform[j].r && !flagr) {
                    dp[j][0] = min(dp[j][0], dp[i][1] + platform[i].h - platform[j].h + platform[i].r - platform[j].l);
                    dp[j][1] = min(dp[j][1], dp[i][1] + platform[i].h - platform[j].h + platform[j].r - platform[i].r);
                    if (j == cnt - 1) {
                        dp[j][0] = min(dp[j][0], dp[i][1] + platform[i].h - platform[j].h);
                        dp[j][1] = min(dp[j][1], dp[i][1] + platform[i].h - platform[j].h);
                    }
                    flagr = true;
                }
            }
        }
        cout << min(dp[cnt - 1][0], dp[cnt - 1][1]) << endl;
    }
    return 0;
}

--(完)--

时间: 2024-11-03 05:43:33

动规-POJ-1661的相关文章

(动规 或 最短路)Help Jimmy(poj 1661)

http://poj.org/problem?id=1661 Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒.当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒.当Jimmy跑到平台的边缘时,开始继续下落.Jimmy每次下落的高度不能超过MAX米,不然就会摔死

POJ 2955 Brackets (动规)

Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2999   Accepted: 1536 Description We give the following inductive definition of a "regular brackets" sequence: the empty sequence is a regular brackets sequence, if s is a reg

POJ 1088 滑雪 (动规)

滑雪 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 75664 Accepted: 28044 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 1

动规,模拟,递推,最长公共子序列

题目链接:http://poj.org/problem?id=1458 解题报告: 1.用二维数组模拟两个字符串上每个子串对应的最长公共子序列. 2.显然,就是要求二维数组最右下的数字 3.递推公式: if(s1[i-1]==s2[j-1]) maxlen[i][j]=maxlen[i-1][j-1]+1; else maxlen[i][j]=max(maxlen[i][j-1],maxlen[i-1][j]); Memory: 1024KTime: 0MSLanguage: C++Result

动规之区间动规小结

区间动规主要有两种方法: 一.是先想出递归式,然后将之转化为滚动数组. 二.或者从小区间贪到大区间. POJ  1159  点击打开链接 AC代码如下: #include<iostream> #include<cstring> #include<algorithm> using namespace std; char a[5005]; short dp[5005][5005]; int min(int a,int b) { return a<b?a:b; } in

sicily 1091 Maximum Sum (动规)

1 //1091.Maximum Sum 2 //b(i,j) = max{b(i,j-1)+a[j], max(b(i-1,t)+a[j])} (t<j) 3 #include <iostream> 4 using namespace std; 5 6 int main() { 7 int t; 8 cin>>t; 9 while (t--) { 10 int n; 11 cin>>n; 12 int a[n+1]; 13 for (int i = 1; i &

[2016-03-29][POJ][1661][]Help Jimmy]

时间:2016-03-29 21:36:50 星期二 题目编号:[2016-03-29][POJ][1661][]Help Jimmy] #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n,x,y,maxh; struct Plat{ int l,r,h; bool operator < (const Plat & a)const{ ret

ACM/ICPC 之 经典动规(POJ1088-滑雪)

POJ1088-滑雪 将每个滑雪点都看作起点,从最低点开始逐个由四周递推出到达此点的最长路径的长度,由该点记下. 理论上,也可以将每一点都看作终点,由最高点开始计数,有兴趣可以试试. 1 //经典DP-由高向低海拔滑雪-求最长路 2 //Memory:372K Time:32 Ms 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 using

!HDU 1176--DP--(矩阵动规)

题意:有一个数轴,从0到10,小明开始在5这个位置.现在天上开始掉馅饼,小明每次只能移动单位一的长度,求小明最多能接到多少馅饼. 分析:刚开始接触动态规划,还没有真正理解动规的思维,所以刚开始的dp做法不知道对不对但是TLE了.正确的方法是建立一个以时间为行位置为列的矩阵,最初map[i][j]代表的是第i时刻j位置掉的馅饼的数量,状态转移方程:map[i][j]=map[i][j]+max(map[i+1][j-1],map[i+1][j],map[i+1][j+1]).也就是从最底层开始往上

【字符串处理+动规】单词的划分

[字符串处理+动规]单词的划分 Time Limit: 1000MS Memory Limit: 2560KB 有一个很长的由小写字母组成字符串.为了便于对这个字符串进行分析,需要将它划分成若干个部分,每个部分称为一个单词.出于减少分析量的目的,我们希望划分出的单词数越少越好.你就是来完成这一划分工作的. 输入格式 第一行,一个字符串.(字符串的长度不超过100)     第二行一个整数n,表示单词的个数.(n<=100)     第3~n+2行,每行列出一个单词. 输出格式     一个整数,