【题号】HDOJ 1242/ZOJ 1649
【题目描述】
Rescue
Time Limit: 2000/1000 MS(Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16010 Accepted Submission(s): 5815
Problem Description
Angel was caughtby the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N* M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel's friends want to save Angel. Their task is: approach Angel. We assumethat "approach Angel" is to get to the position where Angel stays.When there's a guard in the grid, we must kill him (or her?) to move into thegrid. We assume that we moving up, down, right, left takes us 1 unit time, andkilling a guard takes 1 unit time, too. And we are strong enough to kill allthe guards.
You have to calculate the minimal time to approach Angel. (We can move only UP,DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
Input
First linecontains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands forroad, "a" stands for Angel, and "r" stands for each ofAngel's friend.
Process to the end of the file.
Output
For each testcase, your program should output a single integer, standing for the minimaltime needed. If such a number does no exist, you should output a linecontaining "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
【类型】
BFS,优先队列,有点难
【分析】
有普通BFS蒙对的,因为数据太水,但是改改搜索方向也许就A不了。(来自Jason的解释)普通队列+bfs确实是蒙对的,因为击败守卫需要消耗时间1,因此普通队列每一次出队列的元素只是步数上最优,但不一定是时间上最优的,这时即使我们把整个迷宫搜完以最小值作为最优依然不行,因为每一步处理完成都会把该状态标记为已处理vis[i][j]=1,因此,只要有一步不是最优,就会影响后面的结果。这题的正确做法是优先队列,每一次出队都是出时间最少的,这样可以保证每一步最优,并且一旦搜到目标即可立刻结束。a只有1个,但是r可以有多个。
而用优先队列做的话,每次都是走最优(也就是时间最少的步数),这样只要找到“r“就可以直接退出,这样肯定是最优的。
因为有多个r,我们从a开始搜,使用优先队列,每次弹出的是时间最少的,通过对优先队列的操作,使得BFS每一层按优先级进行排序,这样优先级高的就能先进行搜索。
【源代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
usingnamespace std;
constint Max = 200 + 10;
intdir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
intflag;
intn,m;
intsx,sy;
intvis[Max][Max]; //标记数组
charmap[Max][Max];
structnode
{
int x;
int y;
int t; //表示所耗时间
friend bool operator < (node a, node b)
{
return a.t > b.t ; //t小的优先级较大
}
}pre,next;
voidbfs()
{
priority_queue<node> q;
pre.x = sx;
pre.y = sy;
pre.t = 0;
q.push(pre);
while(!q.empty())
{
pre= q.top(); //注意这里是用top,得到优先级最高的元素
q.pop();
if(map[pre.x][pre.y] == 'r') //虽然有多个r,但是只要找到r可以输出啦~因为每次走最优时间的步数,所以一旦找到r肯定是时间最少的
{
flag = 1;
return;
}
for(int i=0; i<4; i++)
{
next.x = pre.x + dir[i][0];
next.y = pre.y + dir[i][1];
if(next.x >=0 &&next.x < n && next.y >= 0 && next.y < m &&!vis[next.x][next.y] && map[next.x][next.y] != '#')
{ //如果可走且不越界,注意:判断越界的条件最好写到最前面,以防后面的数组越界
vis[next.x][next.y] = 1; //一定要记得标记!!!
if(map[next.x][next.y] == 'x') //只有是'x'的时候才需要两步
{
next.t =pre.t + 2;
}
else //其它,包括'.'、'r'、
{
next.t = pre.t + 1;
}
q.push(next);
}
}
}
}
intmain()
{
while(scanf("%d%d",&n,&m) != EOF)
{
flag = 0;
memset(vis, 0, sizeof(vis));
for(int i=0; i<n; i++)
{
getchar();
for(int j=0; j<m; j++)
{
scanf("%c",&map[i][j]);
if(map[i][j] == 'a')
{
sx = i;
sy = j;
}
}
}
vis[sx][sy] = 1;
bfs();
if(flag)
{
cout<<pre.t<<endl;
}
else
{
cout<<"PoorANGEL has to stay in the prison all his life."<<endl;
}
}
return 0;
}