Help Jimmy POJ - 1661 dp

5 篇文章 0 订阅

dpl[i]=x 表示到达第 i 个阶梯的左端点需要的最少时间,dpr[i]=x 相应的久是到达第 i 个阶梯的右端点所需要的最少时间,对于第 i 个阶梯,往下搜寻距离在Max之内的阶梯,假设找到阶梯 j ,阶梯 j 可以使接住从阶梯 i 左端点跳下的人 ,那么到达阶梯 j 左端点的最短时间就是 dpl[j]=min(dpl[j] , 高度差加上走到 j 左端点的距离)
dpr 也是一样的,每个阶梯的左端点和右端点都只能下落一次,假设左端点的被接住了,右端点的还没有,那么搜索的时候就要注意设置标记,不再进入左端点更新,起始位置和终点都要当做阶梯加入数组,还要遍历一遍找到起始位置,不保证起始位置是在最顶端。

#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <math.h>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define LINF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1005;
const long long mod=1e18;
ll MOD(ll a,ll m){return a>m?a%m+m:a;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}

int dpl[1005],dpr[1005];

struct nn
{
    int x1,x2,h;
}bk[maxn];

int cmp(nn a,nn b)
{
    return a.h>b.h;
}

int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int t;
    int n,x,y,Max;
    scanf("%d",&t);
    while(t--){
        memset(dpl,INF,sizeof dpl);
        memset(dpr,INF,sizeof dpr);
        scanf("%d%d%d%d",&n,&x,&y,&Max);
        for(int i=1;i<=n;i++)scanf("%d%d%d",&bk[i].x1,&bk[i].x2,&bk[i].h);
        n++;
        bk[n].x1=bk[n].x2=x;
        bk[n].h=y;
        n++;
        bk[n].x1=-50000;
        bk[n].x2=50000;
        bk[n].h=0;
        sort(bk+1,bk+1+n,cmp);
        int st=1;
        for(int i=1;i<=n;i++){
            if(bk[i].x1==bk[i].x2 && bk[i].x2==x && bk[i].h==y){
                st=i;
                break;
            }
        }
        dpl[st]=0;
        dpr[st]=0;
        for(int i=st;i<=n;i++){
            int l=0,r=0;
            for(int j=i+1;j<=n;j++){
                if(bk[i].h-bk[j].h>Max)break;//too height
                if(bk[j].h==bk[i].h)continue;//euqal height
                if(l==1 && r==1)break;//can not down
                if(bk[j].x1<=bk[i].x1 && bk[i].x1<=bk[j].x2 && l==0){//can go left
                    int costl=(bk[i].h-bk[j].h) + dpl[i] + (bk[i].x1-bk[j].x1);
                    int costr=(bk[i].h-bk[j].h) + dpl[i] + (bk[j].x2-bk[i].x1);
                    if(j==n){
                        costl=bk[i].h-bk[j].h+dpl[i];
                        costr=INF;
                    }
                    dpl[j]=min(dpl[j],costl);
                    dpr[j]=min(dpr[j],costr);
                    l=1;
                }
                if(bk[j].x1<=bk[i].x2 && bk[i].x2<=bk[j].x2 && r==0){//can go right
                    int costl=dpr[i] + (bk[i].h-bk[j].h) + (bk[i].x2-bk[j].x1);
                    int costr=dpr[i] + (bk[i].h-bk[j].h) + (bk[j].x2-bk[i].x2);
                    if(j==n){
                        costl=INF;
                        costr=bk[i].h-bk[j].h + dpr[i];
                    }
                    dpl[j]=min(dpl[j],costl);
                    dpr[j]=min(dpr[j],costr);
                    r=1;
                }
            }
        }
//        for(int i=1;i<=n;i++){
//            cout<<"i = "<<i<<"  dpl="<<dpl[i]<<"  dpr="<<dpr[i]<<"  x1="<<bk[i].x1<<"  x2="<<bk[i].x2
//            <<"  h="<<bk[i].h<<endl;
//        }
        printf("%d\n",min(dpl[n],dpr[n]));
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值