解救小Q(bfs)

解救小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

一道挺容易想到思路,但是做起来有点复杂的题,好题。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<queue>
using namespace std;
#define T 100
struct node
{
	int x,y,cnt;
	node(){}
	node(int _x,int _y,int _cnt):x(_x),y(_y),cnt(_cnt){}
};
node go[30][2];//传送门
char str[T][T];
bool vis[T][T];
int n,m;
int fx[][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int bfs(int x,int y)
{
	memset(vis,false,sizeof(vis));
	queue<node> q;
	q.push(node(x,y,0));
	node p;
	while(!q.empty())
	{
		p = q.front();q.pop();
		for(int i=0;i<4;++i){
			int tx = p.x+fx[i][0],ty = p.y+fx[i][1];
			if(tx>=0&&tx<n&&ty>=0&&ty<m&&str[tx][ty]!='#'&&!vis[tx][ty]){
				vis[tx][ty]=true;
				if(str[tx][ty]=='Q')return p.cnt+1;
				if(str[tx][ty]>='a'&&str[tx][ty]<='z'){//判断是否进入传送门
					int d = str[tx][ty]-'a';
					for(int j=0;j<2;++j){
						if(tx!=go[d][j].x
						   ||ty!=go[d][j].y){
							   tx=go[d][j].x;
							   ty=go[d][j].y;
							   break;
						}
					}
				}
				q.push(node(tx,ty,p.cnt+1));
			}
		}
	}
	return -1;
}

int main()
{
#ifdef zsc
	freopen("input.txt","r",stdin);
#endif
	int N,i,j,x,y;
	scanf("%d",&N);
	while(N--)
	{
		memset(go,-1,sizeof(go));
		scanf("%d%d",&n,&m);
		for(i=0;i<n;++i){
			for(j=0;j<m;++j){
				scanf("\n%c",&str[i][j]);
				if(str[i][j]=='L')x=i,y=j;
				if(str[i][j]>='a'&&str[i][j]<='z'){
					if(go[str[i][j]-'a'][0].x==-1){
						go[str[i][j]-'a'][0].x=i;
						go[str[i][j]-'a'][0].y=j;
					} else {
						go[str[i][j]-'a'][1].x=i;
						go[str[i][j]-'a'][1].y=j;
					}
				}
			}
		}
		printf("%d\n",bfs(x,y));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值