题目链接: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. 基于jenkins自动打包并部署docker环境

    一.实验环境 git                      192.168.200.71 jenkins    192.168.200.72 docker               192.16 ...

  2. 常用的CSS小技巧

    实际开发过程中会遇到一些需要用CSS小技巧处理的布局问题,现在分享几个个人工作中遇到的小问题和解决方案. 1.inline元素间的空白间隙 这里要介绍一个神器font-size:0. 如果你写了个列表 ...

  3. 用两张图告诉你,为什么你的App会卡顿?

    有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? 知道Android究竟是如何在屏幕上显示我们期望的画面的? 对Android的视图架构有整体把握. 学会 ...

  4. 你所不知道的Python | 字符串连接的秘密

    字符串连接,就是将2个或以上的字符串合并成一个,看上去连接字符串是一个非常基础的小问题,但是在Python中,我们可以用多种方式实现字符串的连接,稍有不慎就有可能因为选择不当而给程序带来性能损失. 方 ...

  5. LNMP环境搭建之php安装

    和LAMP安装PHP方法有差别,需要开启php-fpm服务 下载php cd /usr/local/src/ wget http://cn2.php.net/distributions/php-5.6 ...

  6. LFS资料和SSH远程登录全过程

    LFS 即 Linux From Scratch, From Scratch的意思是"白手起家",即从0开始安装Linux,它的所有软件包都需要从源代码开始编译安装.这是通过实际动 ...

  7. cookie、session 和 token 区别

    1.什么是 cookie cookie 是保存在本地终端的数据.cookie 由服务器生成,发送给浏览器,浏览器把 cookie 以 kv 形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该 ...

  8. 在Maven项目中添加代码目录下的配置文件

    问题 Maven 是约定大于配置的一种工具, 通常约定在 src/main/resources 目录下放配置文件, 当我们想要在 src/main/java 代码目录下放置配置文件用来测试, Mave ...

  9. C# 多线程猜想

    公司分配给我一个活,让我给Kong网关做一个获取设置的站点.Kong网关号称几万的QPS的神器,我有点慌,如果因为我的站点拖累了Kong我就是千古罪人. 配合Kong的站点必须要经过性能测试,在性能测 ...

  10. HDU 2016 (水)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2016 题目大意:给你 n 个数,把最小的数和第一个数字互换,然后输出 解题思路: 很水,开数组,遍历并 ...