poj 1661 help jim 动态规划和递推

先前用递推的方法0msAC。进来搞动态规划,刚看到题时想到二叉树,用递归实现了一下,TML。改成dp,16msAC。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 1005
#define oo 0x7fffffff
using namespace std;

struct pai
{
    int l,r,h,minl,minr;
};
pai all[N];

int cmp(const void *a,const void *b)
{
    return (*(pai *)b).h - (*(pai *)a).h;
}
int main()
{
    int t,i,j,k,n,m,p,si,sj,Max;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&n,&si,&sj,&Max);
        for(i = 1;i <= n;i++)
        {
            all[i].minl = all[i].minr = oo;
            scanf("%d%d%d",&all[i].l,&all[i].r,&all[i].h);
        }
        qsort(all+1,n,sizeof(all[0]),cmp);
        for(i = 1;i <= n;i++)//去掉高于下降点和部分不可到的平台。
        {
            if(all[i].h < sj&&all[i].l <= si&&all[i].r>=si)
                break;
        }
        k = i-1;
        all[k].l = all[k].r = si;//将开始下降点视为一个平台。便于统一处理。
        all[k].h = sj;
        all[k].minl = all[k].minr = 0;
        for(i = k;i <= n;i++)
        {
            if(all[i].minl < oo)//跳过不可到达的点
            {
                for(j = i+1;j <= n;j++)//记录左边沿
                {
                    if(all[i].h -all[j].h<=Max&&all[j].l <= all[i].l&&all[j].r >=all[i].l)
                    {
                        p = all[i].minl + all[i].h - all[j].h + all[i].l - all[j].l;
                        if(all[j].minl > p)
                            all[j].minl = p;

                        p = all[i].minl + all[i].h - all[j].h + all[j].r - all[i].l;
                        if(all[j].minr > p)
                            all[j].minr = p;
                        all[i].minl = oo;//覆盖掉不可一步到达地面的点
                        break;
                    }
                }

                for(j = i+1;j <= n;j++)//记录右边沿
                {
                    if(all[i].h -all[j].h<=Max&&all[j].l <= all[i].r&&all[j].r >=all[i].r)
                    {
                        p = all[i].minr + all[i].h - all[j].h + all[i].r - all[j].l;
                        if(all[j].minl > p)
                            all[j].minl = p;

                        p = all[i].minr + all[i].h - all[j].h + all[j].r - all[i].r;
                        if(all[j].minr > p)
                            all[j].minr = p;
                        all[i].minr = oo;//覆盖掉不可一步到达地面的点
                        break;
                    }
                }
            }
        }
        int MM = oo;
        for(i = k;i <= n;i++)
        {
            if(all[i].h <= Max)
            {
                if(all[i].minl != oo && all[i].minl + all[i].h < MM)
                    MM = all[i].minl + all[i].h;
                if(all[i].minr != oo && all[i].minr + all[i].h < MM)
                    MM = all[i].minr + all[i].h;
            }
        }
        printf("%d\n",MM);
    }
    return 0;
}

顺便把0ms的代码也贴出来吧。

#include <cstring>
#include <stdio.h>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;

struct pai
{
    int l;
    int r;
    int h;
};
pai all[1005];
int cmp(const void *a,const void *b)
{
    return (*(pai *)b).h -(*(pai *)a).h;
}
int luo[40005][3];
int main()
{
    int i,j,t,n,m,p,q,flag,x,y,temp,Max,Min,LMin,RMin;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d%d%d",&n,&x,&y,&Max);
        all[0].l = all[0].r = x + 20000;
        all[0].h = y;
        for(i = 1;i <= n;i++)
        {
            scanf("%d%d%d",&all[i].l,&all[i].r,&all[i].h);
            all[i].l += 20000;
            all[i].r += 20000;
        }
        qsort(all,n+1,sizeof(all[0]),cmp);
        memset(luo,0,sizeof(luo));
        luo[x+20000][0] = 1;
        luo[x+20000][1] = 0;
        luo[x+20000][2] = y;
        for(i = 1;i<n+1;i++)
        {
            LMin = RMin = 99999999;
            flag = 0;
            for(j = all[i].l;j <= all[i].r;j++)
            {
                if (luo[j][0]&&luo[j][2] - all[i].h <= Max)
                {
                    temp = luo[j][1] + luo[j][2] - all[i].h + j - all[i].l;
                    if(LMin > temp)
                        LMin = temp;
                    temp = luo[j][1] + luo[j][2] - all[i].h + all[i].r - j;
                    if (RMin > temp)
                        RMin = temp;
                    luo[j][0] = 0;
                    flag = 1;
                }
            }
            if(flag)
            {
                luo[all[i].l][0] = luo[all[i].r][0] = 1;
                luo[all[i].l][1] = LMin;
                luo[all[i].r][1] = RMin;
                luo[all[i].l][2] = luo[all[i].r][2] = all[i].h;
            }
        }
        Min = 99999999;
        for(i = 0;i < 40003;i++)
        {
            if (luo[i][0]&&luo[i][2]<=Max)
            {
                if (Min > luo[i][1] + luo[i][2])
                    Min = luo[i][1] + luo[i][2];
            }
        }
        printf("%d\n",Min);
    }
    return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值