• kuangbin专题十二 POJ1661 Help Jimmy (dp)


    Help Jimmy
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 14214   Accepted: 4729

    Description

    "Help Jimmy" 是在下图所示的场景上完成的游戏。

    场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

    Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

    设计一个程序,计算Jimmy到底地面时可能的最早时间。

    Input

    第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐标的单位都是米。

    Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

    Output

    对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

    Sample Input

    1
    3 8 17 20
    0 10 8
    0 10 13
    4 14 3

    Sample Output

    23


    思路:本来以为是dp二维x, y, 但是不可能开那么大,状态也不好规划。无奈之下看了题解。

    dp[i][0]表示从左边到达i的最小花费
    dp[i][1]表示从右边到达i的最小花费

    然后考虑怎么转移。

    例:

                       -----------------------------------         

               ----------------                  --------------------

    到达最上面的木板可以从左边或右边,下面的一直递推。

    状态转移方程:

    dp[i][0] = h[i] - h[j] +  min( dp[j][0] + l[i] - l[j], dp[j][1] + r[j] - l[i] )

    dp[i][1] = h[i] - h[j] + min( dp[j][0] + r[i] - l[j], dp[j][1] + r[j] - r[i] )

    也就是线段左端 + 交叉的距离 或 线段右端 + 交叉的距离

    其中还有最大高度的细节处理,分为两类,①找不到并且距离之外,②找不到但距离之内

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <math.h>
     4 #include <string.h>
     5 #include <stdlib.h>
     6 #include <string>
     7 #include <vector>
     8 #include <set>
     9 #include <map>
    10 #include <queue>
    11 #include <algorithm>
    12 #include <sstream>
    13 #include <stack>
    14 using namespace std;
    15 #define mem(a,b) memset((a),(b),sizeof(a))
    16 #define mp make_pair
    17 #define pb push_back
    18 #define fi first
    19 #define se second
    20 #define sz(x) (int)x.size()
    21 #define all(x) x.begin(),x.end()
    22 typedef long long ll;
    23 const int inf = 0x3f3f3f3f;
    24 const ll INF =0x3f3f3f3f3f3f3f3f;
    25 const double pi = acos(-1.0);
    26 const double eps = 1e-5;
    27 const ll mod = 1e9+7;
    28 //head
    29 
    30 int dp[1010][2];//dp[i][0]表示从左边到达i的最小花费
    31                 //dp[i][1]表示从右边到达i的最小花费
    32 struct node{
    33     int r, l, h;
    34 }stu[1010];
    35 
    36 bool cmp(node a, node b) {//按高度排序
    37     if(a.h != b.h)
    38         return a.h < b.h;
    39     return a.l < b.l;
    40 }
    41 
    42 bool flag;
    43 int main(int argc, char const *argv[])
    44 {
    45     int _, n, x, y, m;
    46     for(scanf("%d", &_);_;_--) {
    47         memset(dp, 0, sizeof(dp));
    48         scanf("%d%d%d%d", &n, &x, &y, &m);
    49         for(int i = 0; i < n; i++) {
    50             scanf("%d%d%d", &stu[i].l, &stu[i].r, &stu[i].h);
    51         }
    52         sort(stu, stu + n, cmp);
    53         stu[n].l = stu[n].r = x;
    54         stu[n].h = y;
    55         for(int i = 0; i < n + 1; i++) {
    56             flag = false;//标记
    57             for(int j = i - 1; j >= 0; j--) {//
    58                 if(stu[i].h - stu[j].h <= m && stu[i].h > stu[j].h)//保证不摔的前提
    59                     if(stu[j].l <= stu[i].l && stu[j].r >= stu[i].l) {//可以从左边到达的条件
    60                         dp[i][0] = stu[i].h - stu[j].h + min(dp[j][0] + stu[i].l - stu[j].l, dp[j][1] + stu[j].r - stu[i].l);
    61                         flag = true;//标记找到
    62                         break;//递推,找到一个就break
    63                     }
    64             }
    65             if(stu[i].h > m && flag == false) {//如果找不到,并且木板i到达地面高度大于m  -----无穷大
    66                 dp[i][0] = inf;
    67             } else if(flag == false){//找不到,但是到达地面高度 <= m
    68                 dp[i][0] = stu[i].h;
    69             }
    70             flag = false;//同理求出右边的最小花费
    71             for(int j = i - 1; j >= 0; j--) {//
    72                 if(stu[i].h - stu[j].h <= m && stu[i].h > stu[j].h)
    73                     if(stu[j].l <= stu[i].r && stu[j].r >= stu[i].r) {
    74                         dp[i][1] = stu[i].h - stu[j].h + min(dp[j][0] + stu[i].r - stu[j].l, dp[j][1] + stu[j].r - stu[i].r);
    75                         flag = true;
    76                         break;
    77                     }
    78             }
    79             if(stu[i].h > m && flag == false) {
    80                 dp[i][1] = inf;
    81             } else if(flag == false) {
    82                 dp[i][1] = stu[i].h;
    83             }
    84         }
    85         printf("%d
    ", min(dp[n][0], dp[n][1]));//到达木板n的最小花费
    86     }
    87     return 0;
    88 }

     

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Linux的压缩和解压命令
    RabbitMQ消费消息的两种模式:推和拉
    没有开启keepalive,接收消息会超时
    不止背锅!互联网大厂的运维都在干什么?30K的总监来告诉你
    tcp 开启keepalive
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/9572926.html
Copyright © 2020-2023  润新知