#94-[真正的BFS]胜利大逃亡

Description

elfness被魔王抓走了,这次魔王把elfness关在一个n*m的地牢里。地牢的某个地方安装了一个带锁的门,钥匙藏在地牢的另外一个地方,elfness想要通过这个门,就必须先走到藏钥匙的地方取钥匙。刚开始的时候elfness被关在(sx,sy)的位置,而离开地牢的门在(ex,ey)的位置。elfness每分钟只能从一个位置走到相邻四个位置中的其中一个。魔王每t分钟都回地牢视察一次,若发现elfness不在原位置便会把他拎回去。经过若干次的尝试,elfness已经画出了整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候还未到出口都算逃亡失败。

Input

第一行有三个整数n,m,t。接下来的n行m列为地牢的地图,其中包括:
. 代表路
* 代表墙
@ 代表elfness的起始位置
^ 代表地牢的出口
A 代表带锁的门
a 代表钥匙

 

Output

输出为一行,包含一个整数。对于可以成功逃亡的情况,请输出至少需要多少分钟才能离开,如果不能则输出-1。

Sample Input

4 4 100
@..A
a.*.
***.
^…

Sample Output

11

HINT

【数据范围】
对于100%的数据,2<=n,m<=20,t>0

[分析]

BFS

一个点如果没有被访问过,走;

一个点被没带钥匙访问过,如果有钥匙,走。

代码:

#include <iostream>
#include <queue>

#define SIZE 24

using namespace std;

struct node
{
	int x, y, costed;
};

node current, next1;
int visited[SIZE][SIZE];
int dx[4] = {0, 1, 0, -1}; // 四个方向
int dy[4] = {-1, 0, 1, 0};
bool keyed[SIZE][SIZE];
char a[SIZE][SIZE];
queue<node> q;

int main(void)
{
	int n, m, t, i, j, k, entrancex, entrancey, exitx, exity, row, column, f = 0;
	
	cin >> n >> m >> t;
	for (i = 1; i <= n; ++i)
	{
		for (j = 1; j <= m; ++j)
		{
			cin >> a[i][j];
			if (a[i][j] == '@')
			{
				entrancex = i;
				entrancey = j;
				f |= 1;
			}
			else if (a[i][j] == '^')
			{
				exitx = i;
				exity = j;
				f |= 2;
			}
			else if (a[i][j] == 'a')
			{
				f |= 4;
			}
			else if (a[i][j] == 'A')
			{
				row = i;
				column = j;
				f |= 8;
			}
		}
	}
	
	if ((f & 3) != 3) // 没起点没终点,不成
	{
		cout << -1 << endl;
		return 0;
	}
	if ((f & 12) == 8) // 没钥匙,大门改障碍物
	{
		a[row][column] = '*';
	}
	
	for (i = 0; i < SIZE; ++i)
	{
		for (j = 0; j < SIZE; ++j)
		{
			visited[i][j] = -1;
			if (f & 8 == 0)
			{
                keyed[i][j] = true;
            }
			else
			{
                keyed[i][j] = false;
            }
		}
	}
	
	for (i = 0; i <= n + 1; ++i)
	{
		a[i][0] = a[i][m+1] = '*';
	}
	for (j = 0; j <= m + 1; ++j)
	{
		a[0][j] = a[n+1][j] = '*';
	}
	a[entrancex][entrancey] = '.';
	
	current.x = entrancex;
	current.y = entrancey;
	current.costed = 0;
	visited[current.x][current.y] = 0;
	keyed[current.x][current.y] = false;
	
	q.push(current);
	
	while (!(q.empty())) // 基本BFS
	{
		current = q.front();
		q.pop();
		if ((current.x == exitx) && (current.y == exity)) // 到达终点
		{
			if (current.costed < t) // 没到时间,输出结果
			{
				cout << current.costed << endl;
				return 0;
			}
			else // 等于或超过限定时间,不成
			{
				cout << -1 << endl;
				return 0;
			}
		}
		for (k = 0; k < 4; ++k)
		{
			next1.x = row = current.x + dx[k];
			next1.y = column = current.y + dy[k];
			if ((visited[row][column] == -1) || ((visited[row][column] == 0) && (keyed[current.x][current.y]) && (!keyed[row][column])))
			{
				if (a[row][column] == 'a')
				{

					keyed[row][column] = true;
				}
				
				if (((a[row][column] != '*') && (a[row][column] != 'A')) || ((a[row][column] == 'A') && (keyed[current.x][current.y])))
				{
					visited[row][column] = 0;
					next1.x = row;
					next1.y = column;
					next1.costed = current.costed + 1;
					if (keyed[current.x][current.y])
					{
						keyed[row][column] = true;
					}
					q.push(next1);
				}
			}
		}
		
		
	}
	
	cout << -1 << endl; // 到达不了,不成
    
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值