小z身处在一个迷宫中,小z每分钟可以走到上下左右四个方向的相邻格之一。迷宫中有一些墙和障碍物。
同时迷宫中也有一些传送门,当小z走到任意一个传送门时,可以选择传送到其他任意的传送门(传送是不花费时间的),
当然也可以停留在原地。现在小z想知道走出迷宫需要花费的最少时间。
Input
输入第一行为组数T(t<=10)。
对于每组数据第一行为两个整数R和C(1<=R,C<=100)。以下R行每行有C个字符,即迷宫地图。
其中"#“代表墙和障碍物,”."表示空地,"P"表示传送门,"Z"表示小z的起始位置,"W"表示迷宫出口。
对于每组数据保证起始位置和迷宫出口唯一。
Output
对于每组数据,输出走出迷宫的最短时间(单位:分钟)。如果无法走出迷宫则输出"IMPOSSIBLE"。
Sample Input
2
3 4
.Z…
.P#.
##PW
4 4
Z…P
…
##…
W#.P
Sample Output
2
IMPOSSIBLE
以这个题为例来解释迷宫问题。迷宫问题的解决思路一般都是bfs+优先队列,从起点开始,判断这个点的上下左右是否可行,如果可行,将这个点加入到有点队列中,并且从起点到这个点的步数等于这个点的前一个点的步数+1,直到最后找到终点即可。
但是这个题多了一个传送门,即使多了一个传送门,也不影响解题思路。当在遇到第一个传送门的时候,就可以将起点到所有传送门的步数设置为起点到当前传送门的步数,因为可以从一个传送门传送到任意一个传送门,所以当遇到第一个传送门的时候,就可以这样操作了
#include<bits/stdc++.h>
#define inf 1000000
using namespace std;
typedef pair<int,int>Q;//定义结构体
const int k[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//表示上下左右四个方向
int t,r,c,sx,sy,gx,gy,flag,all,m[105][105],z[105][2];//变量会在下面给出用处
char l[105][105];//接收迷宫
int bfs()
{
queue<Q>que;//创建一个优先队列
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
m[i][j]=inf;//m数组拥挤记录起点到每个点的步数,先将他们初始化为一个非常大的数
que.push(Q(sx,sy));//将起点添加到队列中
m[sx][sy]=0;//起点步数设置成0
while(que.size())
{
Q p=que.front();//取出第一个
que.pop();
if(p.first==gx&&p.second==gy)
break;//遇到终点就结束
for(int i=0;i<4;i++)//
{
int x=p.first+k[i][0],y=p.second+k[i][1];//x,y代表这个点上下左右点的坐标
if(x>=1&&x<=r&&y>=1&&y<=c&&l[x][y]!='#'&&m[x][y]==inf)//如果满足条件
{
que.push(Q(x,y));//将这个点加入到优先队列
m[x][y]=m[p.first][p.second]+1;
if(l[x][y]=='P')//如果遇到传送门
{
for(int j=0;j<all;j++){
if(m[z[j][0]][z[j][1]]==inf)//如果没有修改过
{
que.push(Q(z[j][0],z[j][1]));//添加到队列中
m[z[j][0]][z[j][1]]=m[x][y];
}
}
}
}
}
}
if(m[gx][gy]==inf)
return 0;
else
return m[gx][gy];
}
int main()
{
cin>>t;
while(t--)
{
all=0;//用于统计有多少个传送门以及在数组中他们的下标
scanf("%d %d",&r,&c);
getchar();//去除缓冲区中的换行符
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
scanf("%c",&l[i][j]);
if(l[i][j]=='Z')
sx=i,sy=j;//记录起点坐标
if(l[i][j]=='W')
gx=i,gy=j;//记录终点坐标
if(l[i][j]=='P')//如果遇到传送门,就将它储存到数组z中
z[all][0]=i,z[all++][1]=j;
}
getchar();//去除缓冲区的换行符
}
int res=bfs();//开始广搜
if(!res)
printf("IMPOSSIBLE\n");
else
printf("%d\n",res);
}
return 0;
}