POJ--1661(DP)

jimmy的一个游戏,可以从左右端点往下跳,每秒走一米或落一米,落的超过_max会摔死,问到达地面的最短时间,测试用例保证一定有解。

一道基础的DP,太tm考验我了,有些细节容易处理不好,中间卡了下,写错好几个地方,不过我居然一遍过了也真是水……

用了二维的状态,dp[k][0],dp[k][1]分别表示从上一个端点落下来并移动到本k层的左、右端点需要的时间,如果到不了直接在上一个状态恢复到INF表示从此端点掉落会摔死,预处理把开始点也加进去好处理一些,把地面单独判断了下。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#define INF 0X3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
const int maxd=1000+20;
int n,stx,sty,_max;
struct node
{
    int l,r,h;
    bool operator<(const node& rhs) const
    {
        return h>rhs.h;
    }
};
node a[maxd];
int dp[maxd][2];

void solve()
{
    mem(dp,INF);
    dp[0][0]=dp[0][1]=0;
    for(int i=1; i<n; ++i)
    {
        for(int k=i; k<n; ++k)
        {
            if(a[i-1].h-a[k].h>_max)
            {
                dp[i-1][0]=INF;
                break;
            }
            if(a[i-1].l>=a[k].l && a[i-1].l<=a[k].r)
            {
                if(k==n-1)
                {
                    dp[k][0]=min(dp[i-1][0]+a[i-1].h-a[k].h,dp[k][0]);
                    dp[k][1]=min(dp[i-1][0]+a[i-1].h-a[k].h,dp[k][1]);
                }
                else
                {
                    dp[k][0]=min(a[i-1].l-a[k].l+dp[i-1][0]+a[i-1].h-a[k].h,dp[k][0]);
                    dp[k][1]=min(a[k].r-a[i-1].l+dp[i-1][0]+a[i-1].h-a[k].h,dp[k][1]);
                }
                break;
            }
        }

        for(int k=i; k<n; ++k)
        {
            if(a[i-1].h-a[k].h>_max)
              {
                dp[i-1][0]=INF;
                break;
            }

            if(a[i-1].r>=a[k].l && a[i-1].r<=a[k].r)
            {
                if(k==n-1)
                {
                    dp[k][0]=min(dp[i-1][1]+a[i-1].h-a[k].h,dp[k][0]);
                    dp[k][1]=min(dp[i-1][1]+a[i-1].h-a[k].h,dp[k][1]);
                }
                else
                {
                    dp[k][0]=min(a[i-1].r-a[k].l+dp[i-1][1]+a[i-1].h-a[k].h,dp[k][0]);
                    dp[k][1]=min(a[k].r-a[i-1].r+dp[i-1][1]+a[i-1].h-a[k].h,dp[k][1]);
                }
                break;
            }
        }
    }
}

int main()
{
    freopen("1.txt","r",stdin);
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%d%d%d%d",&n,&stx,&sty,&_max);
        a[0].l=stx,a[0].r=stx,a[0].h=sty;
        int cnt=1;
        for(int i=0; i<n; ++i)
        {
            int l,r,h;
            scanf("%d%d%d",&l,&r,&h);
            if(h<=sty)
                a[cnt].l=l,a[cnt].r=r,a[cnt++].h=h;
        }

        a[cnt].l=-30000,a[cnt].r=30000,a[cnt++].h=0;
        n=cnt;
        sort(a,a+n);

        solve();
        printf("%d\n",min(dp[n-1][0],dp[n-1][1]));
       // cout<<INF<<endl;
    }

    return 0;
}
时间: 2024-12-07 17:31:41

POJ--1661(DP)的相关文章

Help Jimmy POJ - 1661 dp

#include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> using namespace std; const int N=1010; const int M=20010; const int INF=0x3f3f3f; struct Time { int x1,x2,h; }a[N]; int dp[N+2][2]; // 0:表示第i的木板左边到底部的最短时间 /

[2016-03-29][POJ][1661][]Help Jimmy]

时间:2016-03-29 21:36:50 星期二 题目编号:[2016-03-29][POJ][1661][]Help Jimmy] #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n,x,y,maxh; struct Plat{ int l,r,h; bool operator < (const Plat & a)const{ ret

M - Help Jimmy POJ 1661 ( 动态规划 )

M - Help Jimmy Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1661 Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒.当Ji

HDU 1087 &amp;&amp; POJ 2533(DP,最长上升子序列).

~~~~ 两道题的意思差不多,HDU上是求最长上升子序列的和,而POJ上就的是其长度. 貌似还有用二分写的nlogn的算法,不过这俩题n^2就可以过嘛.. ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1087 http://poj.org/problem?id=2533 ~~~~ HDU1087: #include<cstdio> #include<cstring> #include<algorithm> #

POJ 3670 &amp;&amp; POJ 3671 (dp)

最长不下降子序列的应用嘛.两题都是一样的. POJ 3670:求给定序列按递增或递减排列时,所需改变的最小的数字的数目. POJ 3671:求给定序列按递增排列时,所需改变的最小的数字的数目. 思路就是求最长不下降子序列,然后剩下的就是需要改变的字母. 最长不下降子序列:(我之前有写过,不懂请戳)http://blog.csdn.net/darwin_/article/details/38360997 POJ 3670: #include<cstdio> #include<cstring

poj 3783 DP 2个鸡蛋扔100层楼的加强版

http://poj.org/problem?id=3783 估计23号之后的排位赛之后我就要退役了,这之前最后再做5天ACM 今天的排位很惨,上次排位也很惨......这道题原来算法课老师讲过,模模糊糊记得方程,但是边界处理有问题, dp[i][j]=min(1+max(dp[k-1][j-1],dp[i-k][j]))   k=1 to 楼数 dp[i][j]:i层楼扔,手里有j个ball 的次数 边界两个:1.dp[1][i]=1,第一层无论手里有几个鸡蛋都是1次,2.dp[i][1]=i

POJ 3034 DP

打地鼠游戏中,你有一个锤子,每一秒钟你可以拿着锤子移动d个单位的距离,必须是直线,掠过的鼠洞中露出的地鼠都会被锤打至,而事先知道从开始时各时间段内出现在老鼠的数量和位置,问题是从游戏开始至结束时,你最多能打到多少只地鼠,开始时锤子可以在任何位置. 题目有个陷阱, 只是说Moles出现的坐标为正,但没说hammer移动的位置要为正,可以为"any position" 所以锤子可以移出矩阵,再从矩阵外一点移进来 例: 20 5 4 1 0 1 0 1 1 0 5 2 1 6 2 0 0 0

POJ 4968 DP||记忆化搜索

给出N个人的平局分X 根据GPA规则计算可能的最高平均GPA和最低平均GPA 可以DP预处理出来所有结果  或者记忆化搜索 DP: #include "stdio.h" #include "string.h" int inf=100000000; double a[11][1100],b[11][1100]; double Max(double a,double b) { if (a<b) return b; else return a; } double M

POJ 2029 DP || 暴力

在大矩形中找一个小矩形 使小矩形包含的*最多 暴力或者DP  水题 暴力: #include "stdio.h" #include "string.h" int main() { int n,m,w,i,s,t,j,k,l,ans,sum,x,y; int map[101][101]; while (scanf("%d",&w)!=EOF) { if(w==0) break; scanf("%d%d",&n,&

POJ 1160 DP

用数轴描述一条高速公路,有V个村庄,每一个村庄坐落在数轴的某个点上,需要选择P个村庄在其中建立邮局,要求每个村庄到最近邮局的距离和最小. cost记录每两个村庄之间建一个邮局的最小代价. 转移方程: dp[j][i]=Min(dp[j][i],dp[k][i-1]+cost[k+1][j]) 前j个村庄建i个邮局=前k个村庄建I-1个邮局+第k+1村庄到第j村庄建一个邮局的代价 #include "stdio.h" #include "string.h" int i