【dp每日一题】POJ 1661 Help Jimmy

POJ 1661 Help Jimmy

大意:

一个小球从((x,y))位置落下,下落速度恒定为1,当落到一个平台时可以向左也可以向右走,速度也是1,走到边缘时继续下落,每次下落距离不能超过k米,现在给出n个平台的左右边缘位置和高度,问小球最快多久能落到地面

思路:

首先将平台按照高度排一下序,然后计算一下小球第一次碰到的是哪个平台,然后从这个平台开始更新dp数组。(dp[i][0])代表到达第i个平台的左边缘最快时间是多少,(dp[0][1])代表到达右边缘。

可以从上到下写也可以从下到上写,从上到下写需要判断dp数组是否为INF,如果为INF代表不能到达第i个平台,那么就不能利用这个平台去更新下面的平台

#include <math.h>
#include <stdio.h>
#include <string.h>

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
using namespace std;

const int N = 1e3 + 5;
typedef long long LL;
int t, n, x, y, k, start = 0,dp[N][2],res;
struct node {
    int l, r, h;
} a[N];
const int INF = 0x3f3f3f3f;
bool cmp(node a, node b) { return a.h > b.h; }

int main() {
    cin >> t;
    while (t--) {
        cin >> n >> x >> y >> k;
        for (int i = 0; i < n; i++) {
            cin >> a[i].l >> a[i].r >> a[i].h;
        }
        memset(dp, 0x3f, sizeof dp);
        sort(a, a + n, cmp);
        res = INF;
        a[n].l = -INF;
        a[n].r = INF;
        a[n].h = 0;
        for (int i = 0; i <= n; i++) {
            if (a[i].r < x || a[i].l > x || a[i].h > y || y - a[i].h > k)
                continue;
            else {
                start = i;
                break;
            }
        }
        if (start == n) {
            cout << y << endl;
            continue;
        }
        dp[start][0] = abs(y-a[start].h)+abs(x - a[start].l);
        dp[start][1] = abs(y-a[start].h)+abs(x - a[start].r);
        for (int i = start; i < n; i++) {
            if (dp[i][0] == INF) continue;
            int flag1 = 0;
            int flag2 = 0;
            for (int j = i + 1; j < n && (flag1 + flag2 != 2); j++) {
                if (a[j].r < a[i].l || a[j].l > a[i].r || a[i].h - a[j].h > k)
                    continue;
                else {
                    if(flag1==0){
                        if(a[j].l<=a[i].l){
                            flag1 = 1;
                            dp[j][0]=min(dp[j][0],dp[i][0]+abs(a[i].l-a[j].l)+abs(a[i].h-a[j].h));
                            dp[j][1]=min(dp[j][1],dp[i][0]+abs(a[i].l-a[j].r)+abs(a[i].h-a[j].h));
                        }
                    }
                    if(flag2==0){
                        if(a[j].r>=a[i].r){
                            flag2 = 1;
                            dp[j][0]=min(dp[j][0],dp[i][1]+abs(a[i].r-a[j].l)+abs(a[i].h-a[j].h));
                            dp[j][1]=min(dp[j][1],dp[i][1]+abs(a[i].r-a[j].r)+abs(a[i].h-a[j].h));
                        }
                    }
                }
            }
            if (flag1 == 0 && (a[i].h <= k)) res = min(res, dp[i][0] + a[i].h);
            if (flag2 == 0 && (a[i].h <= k)) res = min(res, dp[i][1] + a[i].h);
        }
        cout << res << endl;
    }
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14209571.html