[DP] POJ 1661

题意

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

思路

自己的思路本来是每个板子存两个时间,然后分别对两个端点dp
写出来的话差不多就这个样http://blog.csdn.net/yukizzz/article/details/51063447###;

然后看了dalao的博客
直接一个点开左右两维,同时找到左右下方的点,同时对左右做dp
666
dp[i][0] = min(dp[k][0]+l[i]-l[k], dp[k][1]+r[i]-l[k]) + h[i]-h[k]; (左左和左右取最小)
dp[i][1] = min(dp[k][0]+r[i]-l[k], dp[k][1]+r[i]-r[k]) + h[i]-h[k];(右左和右右取最小)
要注意对下方直接为地面的台层的特殊处理,以及应当注意的细节题目都已说明,已在上面标记。

代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>

#define N 1005
#define INF 0x7f7f7f7f

using namespace std;

struct Node {
    int l, r, h;
    //按高度排序
    bool operator< ( const Node &t ) const { return h < t.h; }
} node[ N ];

int dp[ N ][ 2 ];

int main () {
    int T;
    cin >> T;
    while ( T-- ) {
        int n, x, y, mx;
        cin >> n >> x >> y >> mx;
        memset ( dp, INF, sizeof ( dp ) );
        // INpt
        for ( int i = 0; i < n; ++i )
            cin >> node[ i ].l >> node[ i ].r >> node[ i ].h;
        node[ n ].l = x, node[ n ].r = x, node[ n ].h = y;

        //按从小到大高度排序
        sort ( node, node + n );

        for ( int i = 0; i <= n; ++i ) {
            //找到左右两个端点下方合适的板子
            int lp, rp;
            lp = rp = -1;
            for ( int k = i - 1; k >= 0; --k ) {
                if ( lp == -1 && node[ k ].l <= node[ i ].l && node[ k ].r >= node[ i ].l )
                    lp = k;
                if ( rp == -1 && node[ k ].l <= node[ i ].r && node[ k ].r >= node[ i ].r )
                    rp = k;
            }

            //下面没有板子且高度<max
            if ( lp == -1 && node[ i ].h <= mx )
                dp[ i ][ 0 ] = node[ i ].h;
            if ( rp == -1 && node[ i ].h <= mx )
                dp[ i ][ 1 ] = node[ i ].h;

            //左端点
            if ( lp != -1 && node[ i ].h - node[ lp ].h <= mx )
                dp[ i ][ 0 ] = min ( dp[ lp ][ 0 ] + node[ i ].l - node[ lp ].l,
                                     dp[ lp ][ 1 ] + node[ lp ].r - node[ i ].l ) +
                               node[ i ].h - node[ lp ].h;
            if ( rp != -1 && node[ i ].h - node[ rp ].h <= mx )
                dp[ i ][ 1 ] = min ( dp[ rp ][ 0 ] + node[ i ].r - node[ rp ].l,
                                     dp[ rp ][ 1 ] + node[ rp ].r - node[ i ].r ) +
                               node[ i ].h - node[ rp ].h;
        }

        printf ( "%d\n", dp[ n ][ 1 ] );
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值