1. 程式人生 > >#94-[真正的BFS]勝利大逃亡

#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;
}