HDU 1242 Rescue (优先队列 + 广搜)

Rescue

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

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
 
这是昨天比赛的一道题,很明显是一道广搜题,好多人都做出来了,但因为我的搜索学的太烂,导致WA了4次之后还是没有AC。比赛结束之后,队友说要用优先队列加广搜才能过,而我没有用优先队列,搜索时遇到x也没有特殊处理,所以一直过不了。
题意:给出一个n行m列的图,'#'代表墙,'.'代表守卫,'.'代表路,'a'代表angel,'r'代表angel的朋友。angel的朋友要接近angel,可以走'.'和'x',每走一步需要1个单位的时间,当经过x所在的位置时,要杀死x才能继续往前走,但杀死x同样要消耗1个单位的时间。问从r到a最少需要多长时间;如果不能到达,输出” Poor ANGEL has to stay in the prison all his life.”。
分析:使用优先队列,每次从优先队列中取出步数最小的点,从这个点开始搜,直到找到a或者搜索结束。之所以要用优先队列,是因为当遇到类似下面的数据时,用队列如果没有特殊处理,搜索出的步数是错误的。
5 4
####
#xa.
#x#.
#x#.
#r..
直接用队列广搜,结果为7,但最小时间应该是6。
如果不用优先队列,也可以在搜到一个x时,直接把这个点压入队列,不再往它的四个方向搜,能保证这个点能被再次搜到。
用优先队列的代码:
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

char Map[220][220];
int n, m;
struct node
{
    int x, y, step;
    bool operator < (const node &n) const{
        return  n.step < step;
    }   //步数小的优先
}st, ed;

bool judge(int x, int y)  //判断能不能走这一步
{
    if(x >= 1 && x <= n && y >= 1 && y <= m && (Map[x][y] == '.'  || Map[x][y] == 'x' || Map[x][y] == 'a'))
        return true;
    return false;
}

int BFS()
{
    priority_queue <node> Q;
    Map[st.x][st.y] = '#';
        Q.push(st);
    int x, y, time, i;
    node tmp;
    while(!Q.empty())
    {
        tmp = Q.top();
        Q.pop();
        x = tmp.x;
        y = tmp.y;
        time = tmp.step;
        for(i = 0; i < 4; i++)
        {
            tmp.x = x + dx[i];
            tmp.y = y + dy[i];
            if(judge(tmp.x,tmp.y))
            {
                if(Map[tmp.x][tmp.y] == 'a')
                {
                    return time + 1;
                }
                if(Map[tmp.x][tmp.y] == 'x')
                {
                    tmp.step = time + 2;
                    Map[tmp.x][tmp.y] = '#';
                    Q.push(tmp);
                }
                else if(Map[tmp.x][tmp.y] == '.')
                {
                    tmp.step = time + 1;
                    Map[tmp.x][tmp.y] = '#';
                    Q.push(tmp);
                }
            }
        }
    }
    return -1;
}

int main()
{
    int i, j;
    while(~scanf("%d%d",&n,&m))
    {
        for(i = 1; i <= n; i++)
            for(j = 1; j <= m; j++)
            {
                cin >> Map[i][j];
                if(Map[i][j] == 'r')
                {
                    st.x = i;
                    st.y = j;
                    st.step = 0;
                }
                else if(Map[i][j] == 'a')
                {
                    ed.x = i;
                    ed.y = j;
                }
            }
        int ans = BFS();
        if(ans == -1)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

使用队列,不使用优先队列的写法:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;

struct node
{
	int x, y, step, flag;
}st;
int n, m, vis[205][205];
char Map[205][205];

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

bool judge(int x, int y)
{
	if(x < 1 || x > n || y < 1 || y > m || Map[x][y] == '#' || vis[x][y])
		return false;
	return true;
}

int BFS(int a, int b)
{
	queue <node> Q;
	node tmp, temp;
	memset(vis,0,sizeof(vis));
	tmp.x = a;
	tmp.y = b;
	tmp.step = 0;
	tmp.flag = 0;
	vis[a][b] = 1;
	Q.push(tmp);
	while(!Q.empty())
	{
		tmp = Q.front();
		Q.pop();
		if(Map[tmp.x][tmp.y] == 'a')  return tmp.step;
		if(tmp.flag == 1) //当遇到x时,让时间加1,加入队列,不再往它的四个方向搜
		{
			tmp.flag = 0;
			tmp.step++;
			Q.push(tmp);
			continue;
		}
		for(int i = 0; i < 4; i++)
		{
			int nx, ny;
			nx = tmp.x + dx[i];
			ny = tmp.y + dy[i];
			if(!judge(nx,ny))  continue;
			temp.x = nx;
			temp.y = ny;
			temp.step = tmp.step + 1;
			if(Map[nx][ny] == 'x')
				temp.flag = 1;
			else
				temp.flag = 0;
			Q.push(temp);
			vis[nx][ny] = 1;
		}
	}
	return  -1;
}

int main()
{
	int i, j;
	while(~scanf("%d%d",&n,&m))
	{
		for(i = 1; i <= n; i++)
			for(j = 1; j <= m; j++)
			{
				cin >> Map[i][j];
				if(Map[i][j] == 'r')
				{
					st.x = i;
					st.y = j;
				}
			}
		int ans = BFS(st.x,st.y);
		if(ans == -1)
			printf("Poor ANGEL has to stay in the prison all his life.\n");
		else
			printf("%d\n",ans);
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值