解救小Q

解救小Q

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=121832#problem/C

OR

http://acm.uestc.edu.cn/#/problem/show/149




小Q被邪恶的大魔王困在了迷宫里,love8909决定去解救她。
迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡:(,迷宫
里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到
传送阵的另一头。

现在请你帮助love8909算一算,他至少需要走多少步才能解
救到小Q?

Input

第一行为一个整数$T$,表示测试数据组数。

每组测试数据第一行为两个整数$N$,$M$,($1\leq N, M\leq 50$)表示
迷宫的长和宽。

接下来有$N$行,每行$M$个字符,是迷宫的具体描述。

  • .表示安全的位置
  • #表示陷阱,
  • Q表示小Q的位置
  • L表示love8909所在位置,

数据保证love8909只有一个,数据也保证小Q只有一个。

小写字母a-z表示分别表示不同的传送阵,数据保证传送阵
两两配对。

Output

每组数据输出一行,解救小Q所需的最少步数,如果无论如何都
无法救小Q,输出-1

Sample Input

2

5 5
....L
.###.
b#b#a
##.##
...Qa

5 5
....L
.###.
.#.#.
##.##
...Q.

Sample Output

3
-1



例子

10


5 5
....L
.###.
b#b#a
##.##
...Qa


5 5
....L
.###.
.#.#.
##.##
...Q.


4 4
Qa..
b#..
.a#.
.b#L


4 4
Qa..
##..
.a#.
.##L


5 4
....
.#a.
#Q#.
#.#.
.aL.


5 5 
..Qa.
.....
..La.
.....
.....


5 5 
..Qa.
.....
.....
..La.
.....

3  -1 7 8 5 2 2

两个传送门入口走过,出口没走过,传送门强制传送









#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;

struct no
{
	int x,y;
	int step;
};

int dir[4][2] = {0,1,0,-1,1,0,-1,0};
char m[70][70];
int vis[70][70];
int lx,ly;
int qx,qy;
int tr[30][5];
int istr[30];
int xmax,ymax;
int check(int xx,int yy)
{
	if(vis[xx][yy] == 1||m[xx][yy] == '#'||xx<0||yy<0||xx>=xmax||yy>=ymax)
	 return 0;
	return 1;
}

int bfs()
{
	queue<no> q;
	if(!q.empty())
	 q.pop();
	no a,next;
	a.x = lx;
	a.y = ly;
	vis[lx][ly] = 1;
	a.step = 0;
	m[lx][ly] = '#';
	q.push(a);
	while(!q.empty())
	{
		a = q.front();
		q.pop();
		
		

		for(int i = 0;i < 4;i++)
		{
			next = a;
			next.x = a.x+dir[i][0];
			next.y = a.y+dir[i][1];
			if(check(next.x,next.y)) 
		 	  {
		 	  	next.step++; 
		 	  	if(m[next.x][next.y]>='a'&&m[next.x][next.y]<='z')
		 	  	{
		 	  		int aa = (int)m[next.x][next.y] - 'a';
		 	  		if(next.x == tr[aa][0]&&next.y == tr[aa][1])
		 	  		{
		 	  			vis[next.x][next.y] = 1;
		 	  			next.x = tr[aa][2];
						next.y = tr[aa][3];
					   }
					 else
					 {
					 	vis[next.x][next.y] = 1;
		 	  			next.x = tr[aa][0];
						next.y = tr[aa][1];
					   }
					if(m[next.x][next.y] == 'Q')
		{
			return next.step;
		}    
		 	  		q.push(next);
				   }
				 else
				 {
				 	vis[next.x][next.y]= 1;
		 	  		if(m[next.x][next.y] == 'Q')
		{
			return next.step;
		}
		 	  		q.push(next);
				 }  
		 	  	
			   }
		}
		
	}
	return -1;
}





int main()
{
	int T;
	scanf("%d",&T);
	getchar();
	while(T--)
	{
		memset(m,0,sizeof(m));
		memset(istr,0,sizeof(istr));
		memset(vis,0,sizeof(vis));
		memset(tr,0,sizeof(tr));
		
		
		scanf("%d%d",&xmax,&ymax);
		for(int i = 0;i < xmax;i++)
		{
			scanf("%s",m[i]);
			for(int j = 0;j < ymax;j++)
			{
				if(m[i][j] == 'L')
				{
					lx = i;
					ly = j;
				}
				if(m[i][j] == 'Q')
				{
					qx = i;
					qy = j;
				}
				if(m[i][j]>='a'&&m[i][j]<='z')
				{
					if(istr[(int)m[i][j]-'a' ]== 0)
					{
						tr[(int)m[i][j]-'a'][0] = i;
						tr[(int)m[i][j]-'a'][1] = j;
						istr[(int)m[i][j]-'a' ] = 1;
					}
					else
					{
						tr[(int)m[i][j]-'a'][2] = i;
						tr[(int)m[i][j]-'a'][3] = j;
					}
				}
				
			}
				
			
		} 
	
		printf("%d\n",bfs());
		
		
	}
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值