• POJ 1661 Help Jimmy DP


    思路:Jimmy 跳到一块板上后,可以有两种选择,向左走或向右走。走到左端和走到右端所需的时间,容易算出。

    n如果我们能知道,以左端为起点到达地面的最短时间,和以右端为起点到达地面的最短时间,那么向左走还是向右走,就很容选择了。

    n因此,整个问题就被分解成两个子问题,即Jimmy 所在位置下方第一块板左端为起点到地面的最短时间,和右端为起点到地面的最短时间。这两个子问题在形式上和原问题是完全一致的。
    详见代码
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define clc(a,b) memset(a,b,sizeof(a))
     6 #define LL long long
     7 #include<cmath>
     8 const int inf=0x3f3f3f3f;
     9 using namespace std;
    10 int n,X,Y,maxx;
    11 int dp[1010][2];//0表示左边,1表示右边
    12 struct node {
    13     int x,y,h;
    14 } plat[1010];
    15 
    16 int cmp(node p,node q) {
    17     return p.h<q.h;
    18 }
    19 
    20 void left_solve(int i) {
    21     int k=i-1;
    22     while(k>0&&plat[i].h-plat[k].h<=maxx) {
    23         if(plat[i].x>=plat[k].x&&plat[i].x<=plat[k].y) {
    24             dp[i][0]=plat[i].h-plat[k].h+min(plat[i].x-plat[k].x+dp[k][0],plat[k].y-plat[i].x+dp[k][1]);//转移方程
    25             return ;
    26         } else
    27             k--;
    28     }
    29     if(plat[i].h-plat[k].h>maxx)
    30         dp[i][0]=inf;
    31     else
    32         dp[i][0]=plat[i].h;
    33 }
    34 
    35 void right_solve(int i) {
    36     int k=i-1;
    37     while(k>0&&plat[i].h-plat[k].h<=maxx) {
    38         if(plat[i].y>=plat[k].x&&plat[i].y<=plat[k].y) {
    39             dp[i][1]=plat[i].h-plat[k].h+min(plat[i].y-plat[k].x+dp[k][0],plat[k].y-plat[i].y+dp[k][1]);
    40             return;
    41         } else
    42             k--;
    43     }
    44     if(plat[i].h-plat[k].h>maxx)
    45         dp[i][1]=inf;
    46     else
    47         dp[i][1]=plat[i].h;
    48 
    49 }
    50 int solve() {
    51     for(int i=1; i<=n+1; i++) {
    52         left_solve(i);
    53         right_solve(i);
    54     }
    55     return min(dp[n+1][0],dp[n+1][1]);
    56 }
    57 
    58 int main() {
    59 //    freopen("in.txt","r",stdin);
    60     int t;
    61     while(~scanf("%d",&t)) {
    62         while(t--) {
    63             scanf("%d%d%d%d",&n,&X,&Y,&maxx);
    64             for(int i=1; i<=n; i++) {
    65                 scanf("%d%d%d",&plat[i].x,&plat[i].y,&plat[i].h);
    66             }
    67             plat[0].x=-20000;//加入地面和起始点
    68             plat[0].y=20000;
    69             plat[0].h=0;
    70             plat[n+1].x=X;
    71             plat[n+1].y=X;
    72             plat[n+1].h=Y;
    73             sort(plat,plat+n+2,cmp);//从低到高排序
    74 //            for(int i=0;i<=n+1;i++){
    75 //            printf("%d
    ",plat[i].h);
    76 //            }
    77             clc(dp,0);
    78             printf("%d
    ",solve());
    79         }
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    高级排序
    递归
    Linked List
    中缀、后缀、前缀表达式
    队列(queue)
    栈(Stack)
    数组(Array)
    数据结构和算法
    常见排序
    开启
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5288504.html
Copyright © 2020-2023  润新知