POJ1661
题目链接: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的更多相关文章
- POJ1661 Help Jimmy
Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9863 Accepted: 3201 Descriptio ...
- Help Jimmy ~poj-1661 基础DP
Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落, ...
- POJ1661(KB12-M DP)
Help Jimmy Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无 ...
- poj1661 (DP)
题目链接:http://poj.org/problem?id=1661 思路: 把初始位置看成左,右端点均为x0,即长度为0,高度为y0的一个平台,按照平台高度从低到高排序.用dp[i][0],dp[ ...
- 【动态规划】POJ1661 Help Jimmy
Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11621 Accepted: 3827 Descr ...
- kuangbin专题十二 POJ1661 Help Jimmy (dp)
Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14214 Accepted: 4729 Descr ...
- poj1661【DP,左右两端dp】
/* [过滤这一段~~~] 一开始想的[错误的,为自己的总结的写的,读者略过]: 每个状态的点肯定是高度,那么我DP每一层,这样的话就有一层循环,其实这无关复杂度,不会很多时间 错误的是想法是从最高层 ...
- POJ1661 Help Jimmy —— DP
题目链接:http://poj.org/problem?id=1661 Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- [kuangbin带你飞]专题十二 基础DP1
ID Origin Title 167 / 465 Problem A HDU 1024 Max Sum Plus Plus 234 / 372 Problem B HDU 1 ...
随机推荐
- rabbitMQ本地安装(Mac版)
一. 首先测试本机器是否安装wget命令 (可以通过wget www.baidu.com来测试,如果有响应则可直接进入步骤二,如果报错或者提示未安装wget则需要先安装wget) 1http://ft ...
- 【Linux常见命令】split命令
split - split a file into pieces 按照指定的行数或大小分割文件 语法: split [OPTION]... [INPUT [PREFIX]] Output fixed- ...
- web前端开发中的各种居中
居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明 ...
- Java实现zip文件解压[到指定目录]
2019独角兽企业重金招聘Python工程师标准>>> package com.ljheee.ziptool.core; import java.io.File; import ja ...
- C语言编程入门题目--No.15
题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示, 60分以下的用C表示. 1.程序分析:(a>b)?a:b这是条件运算符的基本例子. 2 ...
- 正方形已知两点对角线求另外两点(POJ2002)
至于为什么,上图.转载于MZW_BG 枚举正方形的一条边,此时有上正方形和下正方形. 最后正方形个数/4,因为每个正方形被枚举了4条边 #include <bits/stdc++.h> u ...
- 万盛酒店餐饮管理系统(SpringBoot,SSM,MySQL )
项目源码获取地址: 链接:https://pan.baidu.com/s/1ip0keQruE2crA8vm1n8ZXQ 提取码:kivb 复制这段内容后打开百度网盘手机App,操作更方便哦 [功能包 ...
- 【Scala】代码实现Actor多种需求
文章目录 简单实现Actor并发编程 使用Actor实现发送没有返回值的异步消息 使用Actor实现不间断消息发送 用react方法替代receive方法接收消息 结合case class,通过匹配不 ...
- FPGA的“可编程”使你迷惑吗?
http://www.alteraforum.com.cn/showtopic-7791.aspx FPGA的“可编程”使你迷惑吗? 任何一个硬件工程师对FPGA都不会陌生,就好比C语言对于软件工 ...
- 数学建模(二)优劣解距离法Topsis模型部分
步骤: (一)统一指标类型:指标正向化(转化为极大型)(论文) 越大越好极大型指标,效益型指标 越小越好极小型指标,成本型指标 max-x,max=max{xi} 落在某个区间[a,b]是最好的,区间 ...