解救小Q
时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte
描述
小Q被邪恶的大魔王困在了迷宫里,love8909决定去解救她。迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡:(,迷宫里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到传送阵的另一头。
现在请你帮助love8909算一算,他至少需要走多少步才能解救到小Q? (上下左右四个方向走,传送门可以多次使用)
输入
第一行为一个整数T,表示测试数据组数。每组测试数据第一行为两个整数N,M,(1 <= N, M <= 50)表示迷宫的长和宽。接下来有N行,每行M个字符,是迷宫的具体描述。
'.'表示安全的位置,'#'表示陷阱,
'Q'表示小Q的位置,'L'表示love8909所在位置,
数据保证love8909只有一个,数据也保证小Q只有一个。小写字母'a'-'z'表示分别表示不同的传送阵,数据保证传送阵两两配对。
输出
每组数据输出一行,解救小Q所需的最少步数,如果无论如何都无法救小Q,输出-1。
样例输入
2
5 5
....L
.###.
b#b#a
##.##
...Qa
5 5
....L
.###.
.#.#.
##.##
...Q.
样例输出
3
-1
#include <stdio.h>
#include <string>
#include <iostream>
#include <queue>
#define MAX 55
using namespace std;
char a[MAX][MAX];
int map[MAX][MAX];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//代表上 下 左 右
int n,m;
struct point
{
int x;
int y;
int step;//步数
}s,e;
point find(point t)//找到传送门
{
point x;
int i,j;
for(i = 0; i < n; i++)
{
for(j = 0; j < m; j++)
{
if(a[i][j] == a[t.x][t.y])
{
x.x = i;
x.y = j;
if(i != t.x || j != t.y)
return x;
}
}
}
}
bool bfs()
{
queue <point> q;
int i;
memset(map,0,sizeof(map));
q.push(s);
while(!q.empty())
{
point p = q.front();
q.pop();
if(p.x == e.x && p.y == e.y)
{
printf("%d\n",p.step);
return true;
}
for(i = 0;i < 4; i++)
{
point t;
t.x = p.x + dir[i][0];
t.y = p.y + dir[i][1];
if(t.x >= 0 && t.x < n && t.y >= 0 && t.y < m && a[t.x][t.y] != '#' && map[t.x][t.y] == 0)
{
//printf("1\n");
if(a[t.x][t.y] == '.')
a[t.x][t.y] = '#';
map[t.x][t.y] = 1;
//把传送的那个门标记下 传穿到的门不标记 因为可能还要传过来 如果把传到的那个门标记的话一直会传 会超时
if(a[t.x][t.y] >= 'a' && a[t.x][t.y] <= 'z')//传送
t = find(t);
t.step = p.step + 1;//步数加一
q.push(t);
}
}
}
return false;
}
main()
{
int i,j,k,l,t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m);
for(i = 0;i < n; i++)
scanf("%s",a[i]);
for(i = 0;i < n; i++)
{
for(j = 0;j < m; j++)
{
if(a[i][j] == 'Q')
{
e.x = i;
e.y = j;
}
if(a[i][j] == 'L')
{
s.x = i;
s.y = j;
s.step = 0;
a[i][j] = '#';
}
}
}
if(!bfs())
puts("-1");
}
}