POJ 1661 暴力dp

Posted tiberius

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1661 暴力dp相关的知识,希望对你有一定的参考价值。

题意略。

思路:

很有意思的一个题,我采用的是主动更新未知点的方式,也即刷表法来dp。

我们可以把整个路径划分成横向移动和纵向移动,题目一开始就给出了Jimmy的高度,这就是纵向移动的距离。

我们dp的目标是每个线段端点的横向移动最小值。

有一个小trick,就是有可能Jimmy开始就可以落在地上,没有必要或者说在下落过程中不会有间隔来阻拦。

代码附上:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1005;
const int INF = 0x3f3f3f3f;
const int F = 0x3f;

struct segment
    int l,r,h;
    segment(int l = 0,int r = 0,int h = 0)
        this->l = l,this->r = r,this->h = h;
    
;

segment store[maxn];
int dp[maxn<<1],N,x,h,MAX,t;
bool covered[maxn<<1];

bool cmp(const segment& s0,const segment& s1)
    return s0.h > s1.h;

bool inSegment(int x,segment s)
    return s.l <= x && x <= s.r;


int main()
    scanf("%d",&t);
    while(t--)
        scanf("%d%d%d%d",&N,&x,&h,&MAX);
        for(int i = 0;i < N;++i) scanf("%d%d%d",&store[i].l,&store[i].r,&store[i].h);
        memset(dp,F,sizeof(dp));
        memset(covered,false,sizeof(covered));
        sort(store,store + N,cmp);
        int ans = h,lft,rht,lp,rp,nlft,nrht,nlp,nrp;
        for(int i = 0;i < N;++i)
            lft = i<<1,rht = lft + 1;
            if(inSegment(x,store[i]))
                dp[lft] = x - store[i].l,dp[rht] = store[i].r - x;
                break;
            
        
        for(int i = 0;i < N;++i)
            lft = i<<1,rht = lft + 1;
            lp = store[i].l,rp = store[i].r;
            int cnt0 = 0,cnt1 = 0;
            if(dp[lft] == INF) continue;
            for(int j = i + 1;store[i].h - store[j].h <= MAX && j < N && cnt0 + cnt1 < 2;++j)
                if(store[i].h == store[j].h) continue;
                nlft = j<<1,nrht = nlft + 1;
                nlp = store[j].l,nrp = store[j].r;
                if(!cnt0 && inSegment(lp,store[j]))
                    dp[nlft] = min(dp[nlft],dp[lft] + lp - nlp);
                    dp[nrht] = min(dp[nrht],dp[lft] + nrp - lp);
                    cnt0 = 1;
                
                if(!cnt1 && inSegment(rp,store[j]))
                    dp[nlft] = min(dp[nlft],dp[rht] + rp - nlp);
                    dp[nrht] = min(dp[nrht],dp[rht] + nrp - rp);
                    cnt1 = 1;
                
            
        
        
        
        for(int i = 0;i < N;++i)
            if(store[i].h > MAX) continue;
            for(int j = i + 1;j < N;++j)
                if(inSegment(store[i].l,store[j])) covered[i<<1] = true;
                if(inSegment(store[i].r,store[j])) covered[i<<1 | 1] = true;
            
        
        
        int minn = INF;
        for(int i = N - 1;i >= 0 && store[i].h <= MAX;--i)
            lft = i<<1,rht = lft + 1;
            if(!covered[lft]) minn = min(minn,dp[lft]);
            if(!covered[rht]) minn = min(minn,dp[rht]);
        
        if(minn == INF) minn = 0;
        ans += minn;
        printf("%d\n",ans);
    
    return 0;


/*

1
3 4 4 5
3 5 3
1 7 2
2 6 1
*/

 

以上是关于POJ 1661 暴力dp的主要内容,如果未能解决你的问题,请参考以下文章

POJ1661 Help Jimmy —— DP

Help Jimmy POJ - 1661 数字三角DP

POJ--3311--Hie with the Pie(暴力枚举+floyd)/(状态压缩DP+floyd)

POJ 1661-Help Jimmy-dp

POJ 1661 Help Jimmy(二维DP)

Help Jimmy POJ - 1661 dp