• 【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;
        }
    }
    
  • 相关阅读:
    java 开发之linux 下 tomcat
    Eclipse 工具栏不见了
    开始Java学习(Java之负基础实战)
    error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier
    真机调试iwatch
    创建iwatch 程序选项
    OC--类型为ID 的类的名称
    Cell.reuseIdentifier 指什么
    mongodb在win7下的安装和使用
    mongodb 常用命令
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14209571.html
Copyright © 2020-2023  润新知