杭电 1242(广度优先搜索)
//此题应该从后往前搜索,因为营救者不止一个,第一个找到的营救者时间最短,搜索过程要采用优先队列
#include <iostream>
#include <queue>
using namespace std;
//优先队列默认的是从大到小,此处必须重置为从小到大
typedef struct b
{
int x, y, step;
bool operator < (const b & a) const //重载优先队列
{
return a.step < step;
}
}travel;
char map[201][201];
int m, n;
travel start;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; //设置搜索的4个方向
//采用广度优先搜索,并且将步数小的优先入队(因为遇到守卫和直接到“.”虽然效果相同,但是时间不同此处应优先考虑最短的时间)
int BFS(travel)
{
int i, k;
travel cur, next;
//判断r与被营救对象是否在同一点;
if(map[start.x][start.y] == 'r')
return 0;
priority_queue<travel> pq;
start.step = 0; //不要忘记初始化;
pq.push(start);
while(!pq.empty())
{
cur = pq.top(); //优先级队列使用top
pq.pop();
for(i = 0; i < 4; i ++) //4个方向搜索
{
next.x = cur.x + dir[i][0];
next.y = cur.y + dir[i][1];
if(map[next.x][next.y] == 'r')
return cur.step + 1;
if(next.x >= 1 && next.x <= m && next.y >= 1 && next.y <= n)
{
if(map[next.x][next.y] != '#') //如果不是墙
{
if(map[next.x][next.y] == 'x') //遇到警卫
next.step = cur.step + 2;
else //如果是路
next.step = cur.step + 1;
map[next.x][next.y] = '#'; //将该点设置为墙,代表该点已经加入到队列中
pq.push(next); //将该点压入到队列中
}
}
}
}
return -1;
}
int main()
{
int i, j, steps;
while(scanf("%d %d%*c", &m, &n) != EOF)
{
for(i = 1; i <= m; i ++)
{
for(j = 1; j <= n; j ++)
{
if(j == n)
scanf("%c%*c", &map[i][j]);
else
scanf("%c", &map[i][j]);
if(map[i][j] == 'a') //设置出发者的坐标
{
start.x = i;
start.y = j;
}
}
}
//此处不要忘记初始化
map[start.x][start.y] = '#'; //代表将该点压入到队列中
steps = BFS(start);
if(steps >= 0)
printf("%d\n", steps);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
return 0;
}