Rescue
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 21824 Accepted Submission(s): 7776
Problem Description
Angel was caught by 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 assume that "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 the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the 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.)
Angel's friends want to save Angel. Their task is: approach Angel. We assume that "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 the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the 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 line contains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend.
Process to the end of the file.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend.
Process to the end of the file.
Output
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life."
Sample Input
7 8 #.#####. #.a#..r. #..#x... ..#..#.# #...##.. .#...... ........
Sample Output
13
Author
CHEN, Xue
Source
题意:
Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中。迷宫的长、宽不超过200。 迷宫中有不可以越过的墙以及监狱的看守。
Angel的朋友带了一些救援队来到了迷宫中。他们的任务是:接近Angel。我们假设接近Angel就是到达Angel所在的位置。
假设移动需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死。交给你的任务是,最少要多少单位时间,才能到达Angel所在的地方?(只能向上、下、左、右4个方向移动)
这个题是个很好的搜索题,有一个坑就是一定要从天使开始搜索盆友,因为盆友的数量不定的,我们找的是离天使最近的那个盆友,但是以前不知道的时候从天使搜索竟然没错!数据太水了!
还有一点需要注意的是遇到警卫时时间要加二,如果还是用普通队列就要注意了,不处理的话求出来的一定不是最小时间,所以第一次遇到标记一下,第二次如果碰到标记,时间再加一,不再往4面搜索!但是用优先队列就不用管那么多了,遇到警卫就加二就行了
所以这个题两种解法:
1:优先队列
2:普通队列+特殊处理
下面给出代码!
1:优先队列
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={0,1,0,-1,1,0,-1,0};
int m,n;
struct node
{
int x,y,step;
friend bool operator <(node x,node y)//重载布尔,定义优先队列按步数从小到大排序
{
return x.step>y.step;
}
}now,nex;
bool can(node x)//检查当前点是否可以走
{
if(x.x<0||x.y<0||x.x>m-1||x.y>n-1||vis[x.x][x.y]||map[x.x][x.y]=='#')
return false;
return true;
}
int bfs(int x,int y)
{
priority_queue<node>q;
now.x=x;
now.y=y;
now.step=0;
q.push(now);//将起点入队列
while(!q.empty())
{
now=q.top();
q.pop();
if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果
return now.step;
for(int i=0;i<4;i++)
{
nex.x=now.x+mov[i][0];
nex.y=now.y+mov[i][1];
if(can(nex))
{
if(map[nex.x][nex.y]=='x')
nex.step=now.step+2;//如果当前点可以走,且此点为警卫,步数加二
else
nex.step=now.step+1;//如果当前点可以走,步数加一
vis[nex.x][nex.y]=1;
q.push(nex);//将此点入队列
}
}
}
return -1;
}
int main()
{
int i,j,sx,sy;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=0;i<m;i++)//输入图
{
scanf("%s",map[i]);
for(j=0;j<n;j++)
{
if(map[i][j]=='a')//记录搜索的起点
{
sx=i;
sy=j;
}
}
}
memset(vis,0,sizeof(vis));//标记清0
vis[sx][sy]=1;//起点也只能走一次,保证步数最少
int step = bfs(sx,sy);
if(step==-1)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n",step);
}
return 0;
}
2:普通队列+特殊处理
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={1,0,-1,0,0,1,0,-1};
int m,n;
struct node
{
int x,y,step,flag;
}now,nex;
bool can(node x)//检查当前点是否可以走
{
if(vis[x.x][x.y]||x.x<0||x.x>m-1||x.y<0||x.y>n-1||map[x.x][x.y]=='#')
return false;
return true;
}
int bfs(int a,int b)
{
int i;
queue<node> q;
now.x=a;
now.y=b;
now.step=0;
now.flag=0;
q.push(now);//将起点入队列
while(!q.empty())
{
now=q.front();
q.pop();
if(now.flag)//第二次遇见警卫步数加一,重新标记flag=0
{
now.step++;
now.flag=0;
q.push(now);//这里一定要重新放回队列里
continue;
}
if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果
return now.step;
for(i=0;i<4;i++)
{
nex.x=now.x+mov[i][0];
nex.y=now.y+mov[i][1];
if(can(nex))
{
nex.step=now.step+1;//如果当前点可以走,步数加一
if(map[nex.x][nex.y]=='x')
nex.flag=1;
else
nex.flag=0;//第一次遇见警卫,标记走过,且flag标记为 1
vis[nex.x][nex.y]=1;
q.push(nex);//将此点入队列
}
}
}
return -1;//如果没找到就返回-1
}
int main()
{
int i,j,sx,sy;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=0;i<m;i++)//输入图
{
scanf("%s",map[i]);
for(j=0;j<n;j++)
{
if(map[i][j]=='a')//记录搜索的起点
{
sx=i;
sy=j;
}
}
}
memset(vis,0,sizeof(vis));//标记清0
vis[sx][sy]=1;//起点也只能走一次,保证步数最少
int step = bfs(sx,sy);
if(step==-1)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n",step);
}
return 0;
}