Problem Description

Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反,他们每隔一分钟就变动一次方向.

比如下面的例子里,一开始楼梯在竖直方向,一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向.Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友)告诉Harry正好有一个魔法道具可以帮助他寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的.

Input

测试数据有多组,每组的表述如下:

第一行有两个数,M和N,接下来是一个M行N列的地图,’*’表示障碍物,’.’表示走廊,’|’或者’-‘表示一个楼梯,并且标明了它在一开始时所处的位置:’|’表示的楼梯在最开始是竖直方向,’-‘表示的楼梯在一开始是水平方向.地图中还有一个’S’是起点,’T’是目标,0<=M,N<=20,地图中不会出现两个相连的梯子.Harry每秒只能停留在’.’或’S’和’T’所标记的格子内.

Output

只有一行,包含一个数T,表示到达目标的最短时间.

注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟,并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟,Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向.

Sample Input

5 5
**..T
**.*.
..|..
.*.*.
S....

Sample Output

7

Hint

Hint

地图如下:

挺经典的一个广搜题目!

题意很好理解。做的时候理清思路,注意楼梯的方向,楼梯的方向可以用到达时候的时间的奇偶来判断。因为楼梯只有2个方向!上下,或者左右。

移动到楼梯后面也还要判断下是否越界,楼梯对面是不是墙,是不是已经走过,这3个条件,满足了才能过去。

如果到的时候,楼梯方向与过去的方向不同,就只能等待一分钟,在这个时候,位置不动,时间加1!再进入队列。这个顺序很重要!

不能先过去,然后时间加2,再入队列。这样会超内存,这是很多人用优先队列的原因!

(因为这样的话,你会发现,弹出的node型变量的t会出现t-时间小的会在后面弹出,这样增加了内存的使用!!!)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct node{
int x,y,t;
};
int n,m;
int mx[]={0,1,0,-1};
int my[]={1,0,-1,0};//右,下,左,上
char map[30][30];
int d[30][30];
int tx,ty,sx,sy;
node ft;
int judge(int x,int y){
if(x<0||x>=n||y<0||y>=m){
return 0;
}
if(d[x][y]){
return 0;
}
if(map[x][y]=='*'){
return 0;
}
return 1;
} void bfs(){
queue<node> q;
ft.x=sx;
ft.y=sy;
ft.t=0;
q.push(ft);
d[sx][sy]=1;
while(!q.empty()){
node ff=q.front();
q.pop();
int x=ff.x;
int y=ff.y;
if(map[x][y]=='T'){
printf("%d\n",ff.t);
return;
}
for(int i=0;i<4;i++){
x=ff.x+mx[i];
y=ff.y+my[i];
if(!judge(x,y)){
continue;
}
node nt;
if(map[x][y]=='.'||map[x][y]=='T'){//正常走
nt.x=x;
nt.y=y;
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
continue;
}else if(i==0||i==2){//右和左
if(map[x][y]=='-'&&ff.t%2==0){//可以过去
nt.x=x+mx[i];
nt.y=y+my[i];
if(judge(nt.x,nt.y)){
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}else if(map[x][y]=='|'&&ff.t%2!=0){
nt.x=x+mx[i];
nt.y=y+my[i];
if(judge(nt.x,nt.y)){
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}else {//不能过楼梯,得等一分钟
nt.x=ff.x;
nt.y=ff.y;
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}else{//上和下
if(map[x][y]=='|'&&ff.t%2==0){//可以过去
nt.x=x+mx[i];
nt.y=y+my[i];
if(judge(nt.x,nt.y)){
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}else if(map[x][y]=='-'&&ff.t%2!=0){
nt.x=x+mx[i];
nt.y=y+my[i];
if(judge(nt.x,nt.y)){
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}else {//不能过楼梯,得等一分钟
nt.x=ff.x;
nt.y=ff.y;
nt.t=ff.t+1;
d[nt.x][nt.y]=1;
q.push(nt);
}
}
}
}
} int main(){
while(~scanf("%d%d",&n,&m)){
memset(d,0,sizeof(d));
for(int i=0;i<n;i++){
scanf("%s",map[i]);
for(int j=0;j<m;j++){
if(map[i][j]=='S'){
sx=i,sy=j;
}
}
}
bfs();
}
return 0;
} 测试数据:
/*
3 3
S|.
-..
T..
5 5
**..T
**.*.
..|..
.*.*.
S....
3 4
S|.|
-T-.
.|..
20 20
S.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.|
|.|.|.|.|.|.|.|.|.|.
.|.|.|.|.|.|.|.|.|.T
2 7 7 20
*/

优先队列:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue> using namespace std; char map[30][30];
int vis[30][30];
struct node
{
int x,y,t;
bool operator < (const node &a) const {
return t>a.t;//最小值优先
}
};
int dx[4]= {0,1,0,-1};//右,下,左,上
int dy[4]= {1,0,-1,0};
int n,m;
int sx,sy; int judge(int x,int y)
{
if(x<0||x>=n||y<0||y>=m||map[x][y]=='*'||vis[x][y])
return 0;
return 1;
} int bfs()
{
memset(vis,0,sizeof(vis));
priority_queue<node> q;
node ft;
ft.x=sx;
ft.y=sy;
ft.t=0;
vis[sx][sy]=1;
q.push(ft);
while(!q.empty())
{
ft = q.top();
q.pop();
if(map[ft.x][ft.y]=='T')
{
return ft.t;
}
for(int i=0; i<4; i++)
{
node next;
int nx=ft.x+dx[i];
int ny=ft.y+dy[i];
if(nx<0||nx>=n||ny<0||ny>=m)
{
continue;
}
if(vis[nx][ny]||map[nx][ny]=='*')
{
continue;
}else if(map[nx][ny]=='.'||map[nx][ny]=='T')
{
next.x=nx;
next.y=ny;
next.t=ft.t+1;
vis[nx][ny]=1;
q.push(next);
}
else
{
if(i==0||i==2)//右和左
{
//楼梯是横向,且走的时间为偶数
if(map[nx][ny]=='-'&&ft.t%2==0)
{
nx=nx+dx[i];
ny=ny+dy[i];
if(judge(nx,ny))
{
next.x=nx;
next.y=ny;
next.t=ft.t+1;
vis[nx][ny]=1;
q.push(next);
}
}
else if(map[nx][ny]=='|'&&ft.t%2==1)
{
//楼梯是竖向,且走的时间为奇数
nx=nx+dx[i];
ny=ny+dy[i];
if(judge(nx,ny))
{
next.x=nx;
next.y=ny;
next.t=ft.t+1;
vis[nx][ny]=1;
q.push(next);
}
}
else //方向不对,需要等待一分钟
{
next.x=ft.x;
next.y=ft.y;
next.t=ft.t+1;
q.push(next);
}
}
else //下上
{
if(map[nx][ny]=='-'&&ft.t%2==1)
{
nx=nx+dx[i];
ny=ny+dy[i];
if(judge(nx,ny))
{
next.x=nx;
next.y=ny;
next.t=ft.t+1;
vis[nx][ny]=1;
q.push(next);
}
}
else if(map[nx][ny]=='|'&&ft.t%2==0)
{
nx=nx+dx[i];
ny=ny+dy[i];
if(judge(nx,ny))
{
next.x=nx;
next.y=ny;
next.t=ft.t+1;
vis[nx][ny]=1;
q.push(next);
}
}
else //方向不对,等待一分钟
{
next.x=ft.x;
next.y=ft.y;
next.t=ft.t+1;
q.push(next);
}
}
}
}
}
return -1;
} int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%s",map[i]);
for(int j=0; j<m; j++)
{
if(map[i][j]=='S')
{
sx=i,sy=j;
}
}
}
printf("%d\n",bfs());
}
return 0;
}

HDOJ/HDU 1180 诡异的楼梯(经典BFS-详解)的更多相关文章

  1. HDU 1180 诡异的楼梯(BFS)

    诡异的楼梯 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status ...

  2. hdu 1180:诡异的楼梯(BFS广搜)

    诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Subm ...

  3. HDU 1180 诡异的楼梯【BFS/楼梯随时间变化】

    诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submis ...

  4. HDU 1180 诡异的楼梯(超级经典的bfs之一,需多回顾)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1180 诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others)     ...

  5. hdu 1180 诡异的楼梯 (bfs)

    诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Sub ...

  6. hdu 1180诡异的楼梯(bfs)

    诡异的楼梯 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total Submis ...

  7. hdu 1180 诡异的楼梯

    诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Subm ...

  8. hdu - 1180 诡异的楼梯 (bfs+优先队列)

    http://acm.hdu.edu.cn/showproblem.php?pid=1180 注意点就是楼梯是在harry移动完之后才会改变方向,那么只要统计到达这个点时间奇偶性,就可以知道当前楼梯是 ...

  9. hdu 1180 诡异的楼梯(广搜,简单)

    题目 挺简单的一道广搜题,只要用判断时间是偶数还是奇数就可以判断楼梯的方位,但是我这傻逼居然写了那么久啊那么久,我果然秀逗了,,,, #define _CRT_SECURE_NO_WARNINGS # ...

随机推荐

  1. POJ 3311 Hie with the Pie(DP状态压缩+最短路径)

    题目链接:http://poj.org/problem?id=3311 题目大意:一个送披萨的,每次送外卖不超过10个地方,给你这些地方之间的时间,求送完外卖回到店里的总时间最小. Sample In ...

  2. bzoj2732: [HNOI2012]射箭 半平面交

    这题乍一看与半平面交并没有什么卵联系,然而每个靶子都可以转化为两个半平面. scanf("%lf%lf%lf",&x,&ymin,&ymax); 于是乎就有 ...

  3. 网站开发常用jQuery插件总结(五)滚动条插件nanoscroller

    网站在展示信息时,如果信息量过大,解决方法主要有三种.1.分页,将信息分页显示.2.整页显示,但是页面过长,影响浏览体验.3.使用滚动条,而默认滚动条样式太单一,用户体验不友好.所以我们需要美化滚动条 ...

  4. BestCoder Round #67 (div.2) N*M bulbs

    问题描述 N*M个灯泡排成一片,也就是排成一个N*M的矩形,有些开着,有些关着,为了节约用电,你要关上所有灯,但是你又很懒. 刚好有个熊孩纸路过,他刚好要从左上角的灯泡走去右下角的灯泡,然后离开. 但 ...

  5. 实现目标文件与源码分开的makefile测试实验

    uboot提供了两种编译策略,即可以将生成的目标文件与源码混在一起,也可以将生成的目标文件与源码分开.通过对uboot Makefile的分析,笔者编写了一个简单的实现这种功能的Makfile. 顶层 ...

  6. ajax error函数

    老是去百度 还是自己记下来吧 $.ajax({ url: '/AJAX请求的URL', success: function (data) { alert(data); }, error: functi ...

  7. iBatis系列一

    XML iBatis可以使用xml来作为参数输入以及结果返回:这个功能的优势在于某些特定的场景:还有可以通过DOM方式来作为参数传递:但是这个方式应用的比较少,如果服务器是xml服务器可以采用这种方式 ...

  8. asp.net viewstate的模拟登陆

    其实 VIEWSTATE 不用太在意,倒是 JTCookieID 需要注意,这个才应该是服务器上用来维护 Session 的那个 Cookie.所以,你用 httpclient 的时候,不能上来就直接 ...

  9. python的特殊方法:

    __str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, name, ...

  10. matlab中 hold on 与hold off的用法

    matlab中 hold on 与hold off的用法 hold on 是当前轴及图形保持而不被刷新,准备接受此后将绘制 hold off 使当前轴及图形不在具备被刷新的性质 hold on 和ho ...