题目链接: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. 【JAVA基础】11 Scanner类

    1. Scanner的概述 一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器. Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配.然后可以使用不同的 ne ...

  2. HTML入门(HB、DW)

    一.文字内容 <b></b>  <strong></strong>     /*加粗 <i></i>   <em>& ...

  3. 图论--差分约束--POJ 2983--Is the Information Reliable?

    Description The galaxy war between the Empire Draco and the Commonwealth of Zibu broke out 3 years a ...

  4. Entity framework 加载多层相关实体数据

    Entity framework有3种加载数据的方式:懒汉式(Lazy loading),饿汉式(Eager loading),显示加载(Explicit loading).3种加载方式有各自的优缺点 ...

  5. P2620 虫洞

    题目背景 applepi 想进行宇宙旅行.当然,applepi 知道这是有可能的,因为applepi 的特殊能力能使他观测到宇宙中的虫洞.所谓虫洞就是一个在三维之外的维度打开的快捷通道,通过虫洞能够从 ...

  6. idea使用maven在install时跳过测试

    在右边1处点开maven面板,然后选中2,会发现test已经×掉了,再进行install时将跳过test

  7. vue后台管理系统介绍

    项目GitHub地址:https://github.com/Little-Orange7/cmms-vue 一.简介 很多公司稍微复杂一点的业务,基本上都需要后台管理系统,来对业务进行各个维度的统计. ...

  8. CSS的基础使用

    一,css是什么? CSS全称为“层叠样式表” ,与HTML相辅相成,实现网页的排版布局与样式美化 二,CSS使用方式 1.行内样式/内联样式(单一页面中使用) 借助于style标签属性,为当前的标签 ...

  9. restful 架构风格的curd(增删改查)

    restful架构 概念:REST指的是一组架构约束条件和原则,如果一个架构符合REST的约束条件和原则,就称之为RESTful架构. restful不是一个专门的技术,他是一个规范.规范就是写写代码 ...

  10. spring的aop的注解配置

    一.使用注解的方式配置后置通知 第一步,创建通知类LogAdvice 第二步,要在spring主配置文件中声明以注解的方式配置spring aop  第三步,测试 二.其他异常配置 package c ...