题目链接:http://poj.org/problem?id=1661

解题思路:

  离散化处理 + DP。

  首先,纵坐标除了用来判断老鼠是否会摔死之外基本没用,主要考虑横坐标,只要求出在横坐标上必须走的最短距离,加上题目给出的Y就是答案了。由题目知-20000 <= X, X1[i], X2[i] <= 20000,为了方便后面的处理,我们把这三个数据统一加上20000,不让他出现负数。

  接下来介绍DP的思路,dp[i][x]——代表走到第 i 个平台的横坐标为 x 的点所需走过的最短距离(这里的距离其实都只是考虑横坐标上的距离,不考虑纵坐标,下面的讨论也一样),但是 1 <= N <= 1000 和 x 数据范围显然不允许我们开出这么大的数组,因此我们可以用离散化的技巧,把 x 的数据范围缩小为 [0,2000],这样就勉强可以开出数组了。我们先把平台按照高度由高到低的顺序排好序,则 dp[i][x] = min(dp[i][x] , dp[j][第 j 个平台的左端点坐标](条件:老鼠从第  j 个平台掉到第 i 个平台不会掉死并且这两点之间没有其他平台,右端点一样), dp[j][第 j 个平台的右端点坐标])(j 是从老鼠掉下来的第一个平板到第 i 个平板之间的所有平板)。

  具体细节请看代码。

AC代码:

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=+,inf=0x7ffffff;
struct node{
int x1,x2,h;
}plat[maxn];
bool cmp(node &a, node &b){
return a.h>b.h;
}
int dp[maxn][maxn<<];
int xs[maxn<<],x_on[];
int vis[maxn][]; //0,左端点;1,右端点。这个vis数组是重点,标记第i个平台的左右端点是否已经处理过了
int main(){
int t,X,Y,N,MAX;
scanf("%d",&t);
while(t--){
memset(vis,,sizeof(vis));
memset(x_on,-,sizeof(x_on));
scanf("%d%d%d%d",&N,&X,&Y,&MAX);
X+=; //记得X也要加20000
int x_num=;
for(int i=;i<N;i++){
scanf("%d%d%d",&plat[i].x1,&plat[i].x2,&plat[i].h);
plat[i].x1+=, plat[i].x2+=; //离散化
//*******************************************************************
if(x_on[plat[i].x1]==-){
x_on[plat[i].x1]=x_num; xs[x_num++]=plat[i].x1;
}
if(x_on[plat[i].x2]==-){
x_on[plat[i].x2]=x_num; xs[x_num++]=plat[i].x2;
}
}
sort(xs,xs+x_num);
for(int i=;i<x_num;i++)
x_on[xs[i]]=i;
//******************************************************************** int newx;
sort(plat,plat+N,cmp); int start;
for(start=;start<N;start++){
if(plat[start].x1<=X&&plat[start].x2>=X)
break;
vis[start][]=vis[start][]=;
} //找出老鼠落下的第一个平台,上面的平台不会再用到了,我们随手处理一下访问标记 if(start==N){ //老鼠直接掉到地上的情况也不能忘了考虑哦
printf("%d\n",Y);
continue;
} for(int i=;i<N;i++){
for(int j=;j<x_num;j++) dp[i][j]=inf;
}
newx=x_on[plat[start].x1];
dp[start][newx]=X-plat[start].x1;
newx=x_on[plat[start].x2];
dp[start][newx]=plat[start].x2-X;
for(int i=start+;i<N;i++){
int l=plat[i].x1,r=plat[i].x2,h=plat[i].h;
for(int j=start;j<i;j++){
//如果第j个平台的端点已经被访问了,即对应的vis数组为1,就说明在这个端点到第i个平台之间有平台阻挡
if(vis[j][]&&vis[j][]) continue;
if(plat[j].h-h>MAX) continue; if(!vis[j][]&&plat[j].x1<=r&&plat[j].x1>=l){
vis[j][]=;
dp[i][x_on[l]]=min(dp[i][x_on[l]],dp[j][x_on[plat[j].x1]]+plat[j].x1-l);
dp[i][x_on[r]]=min(dp[i][x_on[r]],dp[j][x_on[plat[j].x1]]+r-plat[j].x1);
}
if(!vis[j][]&&plat[j].x2<=r&&plat[j].x2>=l){
vis[j][]=;
dp[i][x_on[l]]=min(dp[i][x_on[l]],dp[j][x_on[plat[j].x2]]+plat[j].x2-l);
dp[i][x_on[r]]=min(dp[i][x_on[r]],dp[j][x_on[plat[j].x2]]+r-plat[j].x2);
}
}
}
int ans=inf;
for(int i=N-;i>=start;i--){
//从最后一个平台往前遍历,凡是vis标记为0的,即证明这一点没有被处理过,也就证明这一点到地面之间没有阻挡,那么可以从这一点直接跳到地面
if(plat[i].h>MAX) break; //遍历到高度大于MAX的平台就结束
if(!vis[i][])
ans=min(ans,dp[i][x_on[plat[i].x1]]);
if(!vis[i][])
ans=min(ans,dp[i][x_on[plat[i].x2]]);
}
printf("%d\n",ans+Y);
}
return ;
}

POJ1661的更多相关文章

  1. POJ1661 Help Jimmy

    Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9863 Accepted: 3201 Descriptio ...

  2. Help Jimmy ~poj-1661 基础DP

    Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落, ...

  3. POJ1661(KB12-M DP)

    Help Jimmy Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无 ...

  4. poj1661 (DP)

    题目链接:http://poj.org/problem?id=1661 思路: 把初始位置看成左,右端点均为x0,即长度为0,高度为y0的一个平台,按照平台高度从低到高排序.用dp[i][0],dp[ ...

  5. 【动态规划】POJ1661 Help Jimmy

    Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11621   Accepted: 3827 Descr ...

  6. kuangbin专题十二 POJ1661 Help Jimmy (dp)

    Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14214   Accepted: 4729 Descr ...

  7. poj1661【DP,左右两端dp】

    /* [过滤这一段~~~] 一开始想的[错误的,为自己的总结的写的,读者略过]: 每个状态的点肯定是高度,那么我DP每一层,这样的话就有一层循环,其实这无关复杂度,不会很多时间 错误的是想法是从最高层 ...

  8. POJ1661 Help Jimmy —— DP

    题目链接:http://poj.org/problem?id=1661 Help Jimmy Time Limit: 1000MS   Memory Limit: 10000K Total Submi ...

  9. [kuangbin带你飞]专题十二 基础DP1

            ID Origin Title   167 / 465 Problem A HDU 1024 Max Sum Plus Plus   234 / 372 Problem B HDU 1 ...

随机推荐

  1. mybatis if test标签的使用

    2019独角兽企业重金招聘Python工程师标准>>> 在使用mybatis 有时候需要进行判断的. 而我们知道mybatis获取值有两种方式 #{}和${}的. 那么,在mybat ...

  2. 7.JUC线程高级-生产消费问题&虚假唤醒

    描述 生产消费问题在java多线程的学习中是经常遇到的问题 ,多个线程共享通一个资源的时候会出现各种多线程中经常出现的各种问题. 实例说明 三个类:售货员Clerk,工厂Factory,消费者Cons ...

  3. thinkphp5.x系列 RCE总结

    Thinkphp  MVC开发模式 执行流程: 首先发起请求->开始路由检测->获取pathinfo信息->路由匹配->开始路由解析->获得模块.控制器.操作方法调度信息 ...

  4. 创造DotNet Core轻量级框架【一】

    前言 net core 已经出了很久了,网上的各种框架也很多了,但是没看到一个很小很轻的框架,基本都是那种啥功能都有,但是我需要的功能只占他们框架的百分之几,很少很少,所以自己创造一个框架. 因为之前 ...

  5. Spring官网阅读(十八)Spring中的AOP

    文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...

  6. lammps 学习之:系统压力太大,导致原子丢失

    体系压力太大:146981.52bar,体系压强太大 会把原子挤跑 出现原子丢失的情况(lost atoms). 原子丢失: 解决方法:增大体系体积.增加z方向的距离.

  7. python是如何进行参数传递的?

    在分析python的参数传递是如何进行的之前,我们需要先来了解一下,python变量和赋值的基本原理,这样有助于我们更好的理解参数传递. python变量以及赋值 数值 从几行代码开始 In [1]: ...

  8. java接口自动化(五) - 企业级代码管理工具Git的配置

    1.简介 上一篇讲解完如何安装Git后,今天宏哥趁热打铁讲解一下Git的使用,要想使用Git,我们还需要做一些准备工作,首先你的拥有一个Git账号,所以如果你没有的话,就快速注册一个吧. 2.Git注 ...

  9. JavaWeb实战:报价计算系统(layui+tomcat+cookie实现)

    JavaWeb实战:报价计算系统(layui+tomcat+cookie实现) 系统概述: 该系统是文物物流公司的一个小功能模块,用于帮助用户计算运费.点击查看实际效果 系统文档: 添加展品: 在表单 ...

  10. Badboy录制脚本时,提示脚本错误的解决方法

    如下,录制时发生错误: