解救小Q
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
小Q被邪恶的大魔王困在了迷宫里,love8909决定去解救她。迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡:(,迷宫里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到传送阵的另一头。
现在请你帮助love8909算一算,他至少需要走多少步才能解救到小Q?
Input
第一行为一个整数 T
,表示测试数据组数。
每组测试数据第一行为两个整数 N
, M ,( 1≤N,M≤50)表示迷宫的长和宽。
接下来有 N
行,每行 M个字符,是迷宫的具体描述。
.
表示安全的位置#
表示陷阱,Q
表示小Q的位置L
表示love8909所在位置,
数据保证love8909只有一个,数据也保证小Q只有一个。
小写字母a
-z
表示分别表示不同的传送阵,数据保证传送阵两两配对。
Output
每组数据输出一行,解救小Q所需的最少步数,如果无论如何都无法救小Q,输出-1
。
Sample input and output
Sample Input | Sample Output |
---|---|
2 5 5 ....L .###. b#b#a ##.## ...Qa 5 5 ....L .###. .#.#. ##.## ...Q. | 3 -1 |
http://acm.uestc.edu.cn/#/problem/show/149
这道题就是一道bfs的搜索题,但是引入了传送门这种东西,我的办法是标记传送门的第一个节点,当然也可以标记传送过去的那个节点,但是绝对不能一次把两个节点都标记了,因为这个传送门是双向的,他是有可能要回来的,例如
..#.a
.#Q#.
.#.#.
..aL.
这种图的走法就是先进a,到达上面那个a,然后向左走一步,再向右走一步回到下面那个a,再向上走,走到Q,一共是五步。至于怎么标记这些传送门的地址,就各有各的办法了,我是用读入这个图的时候用map标记这种传送门,和find一起用。
代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=55;
bool vst[maxn][maxn]; // 访问标记
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量
char G[maxn][maxn];
int n,m;
struct State // BFS 队列中的状态数据结构
{
int x,y; // 坐标位置
int Step_Counter; // 搜索步数统计器
}Q,L,tmp,tran[maxn][maxn];
bool CheckState(State s) // 约束条件检验
{
if(!vst[s.x][s.y] && G[s.x][s.y]!='#' && s.x>=0 && s.x <n && s.y>=0 && s.y <m) // 满足条件
return 1;
else // 约束条件冲突
return 0;
}
void bfs(State st)
{
queue <State> q; // BFS 队列
State now,next; // 定义2 个状态,当前和下一个
st.Step_Counter=0; // 计数器清零
q.push(st); // 入队
vst[st.x][st.y]=1; // 访问标记
while(!q.empty())
{
now=q.front(); // 取队首元素进行扩展
if(now.x==L.x&&now.y==L.y) // 出现目标态,此时为Step_Counter 的最小值,可以退出即可
{
printf("%d\n",now.Step_Counter); // 做相关处理
return;
}
for(int i=0;i<4;i++)
{
next.x=now.x+dir[i][0]; // 按照规则生成 下一个状态
next.y=now.y+dir[i][1];
next.Step_Counter=now.Step_Counter+1; // 计数器加1
if(CheckState(next)) // 如果状态满足约束条件则入队
{
vst[next.x][next.y]=1; //访问标记
if(G[next.x][next.y]>=97&&G[next.x][next.y]<=122)
{
next.x=tran[now.x+dir[i][0]][now.y+dir[i][1]].x;
next.y=tran[now.x+dir[i][0]][now.y+dir[i][1]].y;
}
q.push(next);
}
}
q.pop(); // 队首元素出队
}
return;
}
int main()
{
int t,i,j;
map<char ,State >::iterator it;
scanf("%d",&t);
while(t--)
{
map<char ,State>MAP;
memset(vst,0,sizeof(vst));
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%s",G[i]);
for(j=0;j<m;j++)
if(G[i][j]>=97&&G[i][j]<=122)
{
it=MAP.find(G[i][j]);
if(it==MAP.end())
{
tmp.x=i;
tmp.y=j;
MAP[G[i][j]]=tmp;
}
else
{
tmp=it->second;
tran[tmp.x][tmp.y].x=i;
tran[tmp.x][tmp.y].y=j;
tran[i][j].x=tmp.x;
tran[i][j].y=tmp.y;
}
}
else if(G[i][j]=='Q')
{
Q.x=i;
Q.y=j;
}
else if(G[i][j]=='L')
{
L.x=i;
L.y=j;
}
}
bfs(Q);
if(!vst[L.x][L.y])
printf("-1\n");
}
return 0;
}