题目描述
“你以为小灰要去走迷宫?我小灰才不走迷宫!作为一个长期潜伏在逸夫楼管道系统里的灰鼠,我才不会在管道里迷路·……迷路…·路········….天哪!
我在哪∑( 口 ||!!!我在管道里迷路啦∑( 口 ||!!!!!!!!!!!谁来救救我!!!!!!!!!!!!!!!“
以上是我们和拥有灰数的灰鼠小灰失去联系之前所收到的最后一段通讯。现在,我们只知道小灰被困在了逸夫楼的网状管道中,但是却不知道他的位置,所以只能展开地毯式搜索!营救小灰刻不容缓!
要知道,管道的环境极其恶劣,小灰怕是撑不了多久,所以我们必须迅速采取行动,营救小灰迫在眉睫!但是,只是着急是没有用的,想要拯救小灰,必须要动脑子!管道实在太窄了,直接进去显然不可能,所以我们从隔壁社团借来了救援机器人,这种机器人可以深入管道内部,探测管道内部的情况。
经过一番勘探,我们大致摸清了管道内部的情况,原来,管道有许多的岔路,列如形如“丄ㄒ”的丁字路,形如“十”的十字路,,形如“7「”的转弯,还有形如“I-”的直路,最神奇的是,最神奇的是,管道中竟然还有灰鼠用灰数制作的形如“O Q”传送
尽管情况复杂,但是这可难不倒聪明的ACMers,经过一番讨论,我们抽象出了管道情况的表示方式:
一、数字1表示该点为不能向右通行的丁字路口,即在该点只能向上向左和向下移动,不能向右移动,也不能从右侧移动到该点。
二、数字2表示该点为不能向左通行的丁字路口
三、数字3表示该点为不能向上通行的丁字路口
四、数字4表示该点为不能向下通行的丁字路口
五、数字5表示该点为可以向四个方移动的十字路口
六、数字6表示该点为能向左右移动的管道
七、数字7表示该点为能向上下移动的管道
八、数字0表示此路不通
九、数字c表示该点为能向左和向下移动的弯道
十、数字d表示该点为能向右和向下移动的弯道
十一、字母a表示该点为能向上和向左移动的弯道
十二、字母b表示该点为能向上和向右移动的弯道
十三、字母O和Q表示两个可以互相传送的传送门(地图上保证有且只有一组传送门),进入传送门后必定会被传送,可以从任意方向进入传送门,传送结束后将到达另一传送门,
之后可以从传送门向任意可移动的方向移动。
十四、字母s表示救援队的出发点
十五、字母t表示小灰的位置
假设救援机器人在管道中每移动一个格子需要消耗的时间为1,每使用一次传送门所需要的时间为1,情况紧急,现在请你计算出救出小灰最少需要多长时间。
输入格式
每个测试点包含一组数据,每组数据的第一行包含两个用空格隔开的整数n,m,表示网格的大小为n行m列,
接来n行,有一个n行m列的地图,其中第i行j列的符号表示地图中第i行j列的位置的物体种类。
输出格式
请你输出营救小灰所需要的最短时间。(题目保证一定能救出小灰!)
输入样例
5 5
s333c
0ba77
d5Oa7
2555a
b4Q5t
输出样例
9
解题思路
一道模拟加广搜的题,模拟重点在管道的连通上,画图比较清楚,比赛的时候没画图,没写函数,四个方向全写在了bfs里,if里面套for,for里面套if//////着实是看吐了
AC代码
#include <bits/stdc++.h>
#define fr(i,p) for(int i=0;i<p;i++)
using namespace std;
int dir[][2]={1,0,-1,0,0,1,0,-1};//下 上 右 左
const int maxn=1e2+5;
char mp[maxn][maxn];
int n,m,s_x,s_y,Q_x,Q_y,O_x,O_y;
struct cp{int x,y,s;cp(int xx,int yy,int ss):x(xx),y(yy),s(ss){}};
queue <cp> myq;
bool book[maxn][maxn];
void init()//初始化
{
fr(i,n)fr(j,m)
{
book[i][j]=0;//clear标记数组
if(mp[i][j]=='s'){s_x=i,s_y=j;}//找营救队的位置
else if(mp[i][j]=='Q'){Q_x=i,Q_y=j;}//找Q的位置
else if(mp[i][j]=='O'){O_x=i,O_y=j;}//找O的位置
}
}
/*****************左左左左左**********************/
void run_left(int tx,int ty,cp temp)
{
//当前这个点能否往左走
if(mp[temp.x][temp.y]=='2'||mp[temp.x][temp.y]=='7'
||mp[temp.x][temp.y]=='d'||mp[temp.x][temp.y]=='b')
return ;
//当前这个点能否从左边过来
if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
mp[tx][ty]=='1'||mp[tx][ty]=='7'||mp[tx][ty]=='0'
||mp[tx][ty]=='a'||mp[tx][ty]=='c')
return ;
else
myq.push(cp(tx,ty,temp.s+1));
}
/******************下下下下下*********************/
void run_down(int tx,int ty,cp temp)
{
//当前这个点能否往下走
if(mp[temp.x][temp.y]=='4'||mp[temp.x][temp.y]=='6'
||mp[temp.x][temp.y]=='a'||mp[temp.x][temp.y]=='b')
return ;
//当前这个点能否从下边过来
if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
mp[tx][ty]=='3'||mp[tx][ty]=='6'||mp[tx][ty]=='0'
||mp[tx][ty]=='c'||mp[tx][ty]=='d')
return ;
else
myq.push(cp(tx,ty,temp.s+1));
}
/***************上上上上上************************/
void run_up(int tx,int ty,cp temp)
{
//当前这个点能否往上走
if(mp[temp.x][temp.y]=='3'||mp[temp.x][temp.y]=='6'
||mp[temp.x][temp.y]=='c'||mp[temp.x][temp.y]=='d')
return ;
//当前这个点能否从上面过来
if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
mp[tx][ty]=='4'||mp[tx][ty]=='6'||mp[tx][ty]=='0'
||mp[tx][ty]=='a'||mp[tx][ty]=='b')
return ;
else
myq.push(cp(tx,ty,temp.s+1));
}
/**************右右右右右*************************/
void run_right(int tx,int ty,cp temp)
{
//当前这个点能否往右走
if(mp[temp.x][temp.y]=='1'||mp[temp.x][temp.y]=='7'
||mp[temp.x][temp.y]=='c'||mp[temp.x][temp.y]=='a')
return ;
//当前这个点能否从右过来
if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
mp[tx][ty]=='2'||mp[tx][ty]=='7'||mp[tx][ty]=='0'
||mp[tx][ty]=='b'||mp[tx][ty]=='d')
return ;
else
myq.push(cp(tx,ty,temp.s+1));
}
void bfs()
{
myq.push(cp(s_x,s_y,0));
while(!myq.empty())
{
cp temp=myq.front();
if(mp[temp.x][temp.y]=='t')//营救出口
{
cout<<temp.s<<endl;
return ;
}
if(mp[temp.x][temp.y]=='Q'&&book[O_x][O_y]==0)//传送
myq.push(cp(O_x,O_y,temp.s+1));
if(mp[temp.x][temp.y]=='O'&&book[Q_x][Q_y]==0)//传送
myq.push(cp(Q_x,Q_y,temp.s+1));
fr(i,4)// 下 上 右 左
{
int tx=temp.x+dir[i][0];
int ty=temp.y+dir[i][1];
switch(i)
{
case 0:run_down(tx,ty,temp);break;
case 1:run_up(tx,ty,temp);break;
case 2:run_right(tx,ty,temp);break;
case 3:run_left(tx,ty,temp);break;
}
}
book[temp.x][temp.y]=1;
myq.pop();
}
}
int main()
{
while(cin>>n>>m)
{
fr(i,n)fr(j,m)cin>>mp[i][j];
init();
bfs();
}
return 0;
}