【bfs+优先队列】POJ2049-Finding Nemo
基本上算是普通但略有些繁琐的广搜。给出的墙面和门的坐标为点,而Nemo位于方格中。
【思路】
首先思考一下如何存储下整个坐标系。我们预先约定,用一个方格的左下角顶点坐标来作为这个方格的坐标。map[i][j][k]数组是一个三维数组,下标前两位表示当前方格坐标为(i,j),第三位依次表示方格的上下左右,对应下标中的元素用0表示空白,1表示有墙,2表示有门。读入数据的时候,同时修改该墙或门两侧的方格。注意dx、dy数组一定要与上下左右的方向对应,方便后续操作。最后读入Nemo的坐标只要去尾法强制取整即可。但是看别人讨论,强制取整不能用(int),否则会WA,我试了一下的确会有这种问题。用floor会直接将float赋给int可以解决问题。
广搜时从Nemo开始倒退,由于我们需要比较的是经过最小的门数,而不是走的最小步数,广搜的队列必须要用优先队列存储。
【剪枝】
当没有任何一道门或墙的时候,即m=n=0时,直接输出0;
当Nemo在迷宫最大范围外,即fx>199||fy>199||fx<0||fy<0,直接输出0;
读入数据时记录下门或墙纵坐标的最大最小值,最小值为起点减1,最大值为起点加上长度。当前坐标中某一位大于这个极值时,可以直接走到终点,直接输出此时的步数;
(和上一步略有重复)当前坐标大于门或墙横纵坐标最大值时,只会越走越远,所以可以制止搜索继续。但不能把(nowx<0 || nowy<0 || nowx>limitx || nowy>limity) 写成(nowx<littlex || nowy<littley || nowx>limitx || nowy>limity),因为Nemo倒推时总是越来越趋向于(0,0)点,这么判断会使得大多数情形都变成无解。
#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=;
const int INF=;
struct point
{
int x,y,num;
bool operator < (const point &x) const
{
return num>x.num;
/*优先队列设置为小顶堆*/
}
};
int m,n;
int limitx,limity,littlex,littley,fx,fy;
int map[MAXN][MAXN][];
int step[MAXN][MAXN];
/*方格的坐标用左下角顶点坐标来记录*/
/*第三维依次代表上下左右*/
/*数组内元素的值0:空白 1:墙 2:门*/
int dx[]={,,-,};
int dy[]={,-,,};
/*d数组要对应上下左右的顺序,方便后续操作*/
int vis[MAXN][MAXN];
float initx,inity; void initwall()
{
memset(map,,sizeof(map));
limitx=limity=-;
littlex=littley=INF;
int x,y,d,t;
for (int i=;i<m;i++)
{
cin>>x>>y>>d>>t;
if (x+t>limitx) limitx=x+t;
if (y+t>limity) limity=y+t;
if (x-<littlex) littlex=x-;
if (y-<littley) littley=y-;
if (d==)
{
for (int j=x;j<x+t;j++)
{
map[j][y][]=;
if (y>=) map[j][y-][]=;
}
}
else
{
for (int j=y;j<y+t;j++)
{
map[x][j][]=;
if (x>=) map[x-][j][]=;
}
}
}
} void initdoor()
{
int x,y;
int d;
for (int i=;i<n;i++)
{
scanf("%d%d%d",&x,&y,&d);
if (x+>limitx) limitx=x+;
if (y+>limity) limity=y+;
if (x-<littlex) littlex=x-;
if (y-<littley) littley=y-;
if (d==)
{
map[x][y][]=;
if (y>=) map[x][y-][]=;
}
else
{
map[x][y][]=;
if (x>=) map[x-][y][]=;
}
}
} int bfs()
{
for (int i=;i<=limitx;i++)
for (int j=;j<=limity;j++) step[i][j]=INF;
int ans=INF;
point in,out;
memset(vis,,sizeof(vis));
step[fx][fy]=;
in.x=fx;in.y=fy;in.num=;
priority_queue<point> que;
/*由于队列记录的是经过的门数而非步数,要用优先队列*/
que.push(in);
while (!que.empty())
{
out=que.top();
que.pop();
if (out.x== && out.y==|| out.x==littlex || out.y==littley || out.x==limitx || out.y==limity)
{
return out.num;
}
/*如果到达终点或超出最大范围,直接输出结果*/
for (int i=;i<;i++)
{
int nowx=out.x+dx[i],nowy=out.y+dy[i],nownum=out.num;
if (nowx< || nowy< || nowx>limitx || nowy>limity) continue;
if (map[out.x][out.y][i]==) continue;
/*前进的方向不能被门阻隔*/
if (map[out.x][out.y][i]==) nownum++;
/*如果前进的方向是一扇门,则加一*/
if (step[nowx][nowy]==INF || nownum<step[nowx][nowy]&& nownum<ans)
{
in.x=nowx;in.y=nowy;in.num=nownum;
que.push(in);
step[nowx][nowy]=in.num;
}
}
}
return -;
/*无解时返回-1*/
} int main()
{
while (scanf("%d%d",&m,&n))
{
if (m==n && m==-) break; initwall();
initdoor();
cin>>initx>>inity;
fx=initx;
fy=inity;
/*由于方格坐标由左下角定点来表示,强制转换为int型即可*/
if (n== && m==||fx>||fy>||fx<||fy<)
cout<<<<endl;
else cout<<bfs()<<endl;
}
return ;
}
【bfs+优先队列】POJ2049-Finding Nemo的更多相关文章
- POJ 2049 Finding Nemo bfs 建图很难。。
Finding Nemo Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 6952 Accepted: 1584 Desc ...
- POJ 2049— Finding Nemo(三维BFS)10/200
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013497151/article/details/29562915 海底总动员.... 这个题開始 ...
- Finding Nemo 分类: POJ 2015-07-11 10:11 10人阅读 评论(0) 收藏
Finding Nemo Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 8117 Accepted: 1883 Desc ...
- POJ 2049 Finding Nemo
Finding Nemo Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 8631 Accepted: 2019 Desc ...
- POJ 1724 ROADS(BFS+优先队列)
题目链接 题意 : 求从1城市到n城市的最短路.但是每条路有两个属性,一个是路长,一个是花费.要求在花费为K内,找到最短路. 思路 :这个题好像有很多种做法,我用了BFS+优先队列.崔老师真是千年不变 ...
- hdu 1242 找到朋友最短的时间 (BFS+优先队列)
找到朋友的最短时间 Sample Input7 8#.#####. //#不能走 a起点 x守卫 r朋友#.a#..r. //r可能不止一个#..#x.....#..#.##...##...#.... ...
- HDU 1428 漫步校园 (BFS+优先队列+记忆化搜索)
题目地址:HDU 1428 先用BFS+优先队列求出全部点到机房的最短距离.然后用记忆化搜索去搜. 代码例如以下: #include <iostream> #include <str ...
- hdu1839(二分+优先队列,bfs+优先队列与spfa的区别)
题意:有n个点,标号为点1到点n,每条路有两个属性,一个是经过经过这条路要的时间,一个是这条可以承受的容量.现在给出n个点,m条边,时间t:需要求在时间t的范围内,从点1到点n可以承受的最大容量... ...
- BFS+优先队列+状态压缩DP+TSP
http://acm.hdu.edu.cn/showproblem.php?pid=4568 Hunter Time Limit: 2000/1000 MS (Java/Others) Memo ...
随机推荐
- vue双向绑定原理源码解析
当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/maxlove123 ...
- Angular2.0 基础: Form
对于Angular2.0 的Form表单中的隐藏和验证,个人觉得还是挺有意思的. 1.通过ngModel 跟踪修改状态与验证. 在表单中使用 ngModel 可以获得更多的控制权,包括一些常用的验证. ...
- 2017-2018-1 20179205《Linux内核原理与设计》第二周作业
<Linux内核原理与分析>第二周作业 本周视频学习情况: 通过孟老师的视频教程,大致对风诺依曼体系结构有了一个初步的认识,视频从硬件角度和程序员角度对CPU和Main Memory(内存 ...
- vs 2015 插件 supercharger 破解方式
亲测有效:效果如图 方法如下: 1.打开Supercharger的options; 2.点击Pricing & Registration 3.复制 license 然后再按Paste &am ...
- linux中使用mysql数据库
在安装完数据库后,如果没有设置root的mysql密码,在命令行输入mysql即可进入数据库 show databases;(有分号):查看当前存在的数据库 create database 名字:创建 ...
- Laravel 5.2 数据库迁移和数据填充
一.数据库迁移 Laravel 的数据库迁移提供了对数据库.表.字段.索引的一系列相关操作.下面以创建友情链接表为例. 1. 创建迁移 使用 Artisan 命令 php artisan make: ...
- iOS一个项目开始创建, 部署到git服务器
在做iOS开发时, 最开始可能你的经理部署项目, 所以你不会插手, 只是直接从git上clone下来然后就开始撸码, 如果有一天你做经理了, 你怎么去部署一个项目呢, 下面我来过一遍流程 1. 首先需 ...
- springboot在不同环境下进行不同的配置
原文链接:http://www.cnblogs.com/java-zhao/p/5469183.html 不同的环境设置一个配置文件,例如:dev(开发)环境下的配置设置在application-de ...
- [New learn]AutoLayout调查基于IB
代码:https://github.com/xufeng79x/AutoLayout-IB 1.简介 Autolayout旨在解决不同高宽度的屏幕下的显示问题,通过增加给控件增加约束来达到不同屏幕间的 ...
- Memcached内存缓存技术
Memcached是什么,有什么作用? Memcached是一个开源的.高性能的内存缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思. Memcached通过在事先规划好的内存空间 ...