HDOJ1242. Rescue(BFS+priority_queue)

19 篇文章 0 订阅
3 篇文章 0 订阅

Rescue

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34431    Accepted Submission(s): 12019


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.)
 

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.
 

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

【分析】BFS+priority_queue(优先队列)

        题意:Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中。迷宫的长、宽不超过200。

                   迷宫中有不可以越过的墙以及监狱的看守。Angel的朋友带了一些救援队来到了迷宫中。他们的任务是:接近Angel。

                   我们假设接近Angel就是到达Angel所在的位置。假设移动需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死。

                   问:最少要多少单位时间,才能到达Angel所在的地方?(只能向上、下、左、右4个方向移动)

        注意以下三个要点:

        (1)‘a’--Angel  'r'--Angel的朋友  ‘x’--看守  ‘.’--空地(可走区域)  ‘#’--障碍(不可走区域);

        (2)"Angel's friends"提示我们Angel('a')只有一个,而她的朋友('r')可以有多个,因此在搜索时逆向处理一下,从天使向周围搜索,找"离她最近"的朋友;

        (3)移动需要1单位时间,杀死一个看守也需要1单位时间。也就是说,搜索时遇到'.'时间+1,而遇到'x'时间+2,因此可使用优先队列(priority_queue)实现该过程。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAX=210;
int N,M;
int sx,sy,mint;    //(sx,sy)-公主位置 mint-最少营救时间 
char map[MAX][MAX];//迷宫地图 
int vis[MAX][MAX]; //点的访问标记 
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};  //移动方向(上/下/左/右) 
struct node
{
	int x;
	int y;
	int t;
	//重载'<'运算符,即定义优先队列按时间递增排序
	friend bool operator <(const node &a,const node &b)
	{
		return (a.t>b.t);
	}
} cur,nxt;
//检测当前位置(x,y)是否在迷宫内、未走过且可以走 
bool check(int x,int y)
{
	return (x>=0 && x<N && y>=0 && y<M && !vis[x][y] && map[x][y]!='#');
}
int bfs()
{
	int i;
	priority_queue<node> q;
	//搜索起点即公主的位置 
	cur.x=sx;
	cur.y=sy;
	cur.t=0;
	//将起点入队 
	q.push(cur);
	//标记已走过(即只能走一次,以保证用时最少) 
	vis[cur.x][cur.y]=1;
	while(!q.empty())
	{
		cur=q.top();
		q.pop();
		//找到Angel的朋友,结束整个搜索过程(此时搜出的朋友即离Angel最近的) 
		if(map[cur.x][cur.y]=='r')
			return cur.t;
		//试探当前位置(cur.x,cur.y)周围的4个位置 
		for(i=0;i<4;i++)
		{
			nxt.x=cur.x+dir[i][0];
			nxt.y=cur.y+dir[i][1];
			//下一位置可走 
			if(check(nxt.x,nxt.y))
			{
				//下一位置为警卫,耗时+2 
				if(map[nxt.x][nxt.y]=='x')
					nxt.t=cur.t+2;
				//否则耗时+1 
				else
					nxt.t=cur.t+1;
				//标记下一位置(nxt.x,nxt.y)已走过 
				vis[nxt.x][nxt.y]=1;
				//将下一位置(nxt.x,nxt.y)入队 
				q.push(nxt);
			}
		}
	}
	return -1;
}
int main()
{
	int i,j;
	while(scanf("%d %d",&N,&M)!=EOF)
	{
		for(i=0;i<N;i++)
			scanf("%s",map[i]);
		for(i=0;i<N;i++)
		{
			for(j=0;j<M;j++)
			{
				//公主位置 
				if(map[i][j]=='a')
				{
					sx=i;
					sy=j;
				}
			}
		}
		memset(vis,0,sizeof(vis));
		mint=bfs();
		//无解 
		if(mint==-1)
			printf("Poor ANGEL has to stay in the prison all his life.\n");
		//有解 
		else
			printf("%d\n",mint);
	}
	return 0;
}
/*
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........

7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##r.
.#......
....r...

3 3
#a#
..#
.#r 
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值