BFS (Rescue) Another solution

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1242

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


题意

美丽的天使被 Moligpy 人抓住了,天使的盆友(注意friends 可能不止一个盆友)要去救她 。在N * M 的牢笼里有 # 代表墙壁,.  代表道路,r 代表盆友 ,a 、x 分别代表天使和士兵。盆友每走一步用时一个单位时间,杀死一个士兵也需要用一个单位时间。问我们最快能救天使用时多久。

思路

此题和先前的最短路径有很大程度的相似,不同点在于这题要对士兵特殊处理。

参考他人的博客:https://blog.csdn.net/nvliba/article/details/48002883  主要是 从天使为起始点求离天使最近的那个盆友 (分别用优先队列和普通队列的特殊处理),写的很不错,代码风格很清新 。

我这篇是从盆友出发找天使的方法,因为盆友个数不确定所以用一个数组记录盆友的位置,来一个个带入bfs() 求时间,最后比较这些盆友谁能在最短时间把天使救出来。我用的也是优先队列来处理士兵的问题(感觉理解了优先队列的话,解这题更方便一点。)


code

#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;

int n,m;
int sx,sy;           // 起始点 每个盆友的位置
int gx,gy;           // 天使的位置
int a[210],b[210];   // 存放盆友位置
int vis[210][210];
int d[4][2]={1,0,0,1,-1,0,0,-1};
char maze[210][210];

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(vis[x.x][x.y]==1 || x.x<0 || x.x>n-1 || x.y<0 || x.y>m-1 || maze[x.x][x.y]=='#')
        return false;
    else
        return true;
}

int bfs(int a,int b)
{
    priority_queue <node> q;
    now.x=a;
    now.y=b;
    now.step=0;
    q.push(now);

    while(!q.empty())
    {
        now=q.top();
        q.pop();

        if(maze[now.x][now.y]=='a')
            return now.step;

        for(int i=0;i<4;i++)
        {
            nex.x=now.x+d[i][0];
            nex.y=now.y+d[i][1];

            if(can(nex))
            {
                if(maze[nex.x][nex.y]=='x')    // 遇见士兵时间加 2
                    nex.step=now.step+2;
                else
                    nex.step=now.step+1;

                vis[nex.x][nex.y]=1;
                q.push(nex);
            }
        }
    }
    return INF;            // 返回INF可以更好地去判断各个盆友到天使的最短距离距离
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int ans=0;
        int Min=INF;      // 小技巧为更好地去判断各个盆友到天使的最短距离距离

        for(int i=0;i<n;i++)
        {
            scanf("%s",maze[i]);
            for(int j=0;j<m;j++)
            {
                if(maze[i][j]=='a')
                {
                    gx=i;
                    gy=j;
                }
                if(maze[i][j]=='r')
                {
                    a[ans]=i;
                    b[ans]=j;
                    ans++;
                }
            }
        }

        for(int i=0;i<ans;i++)
        {
            int res;
            
            memset(vis,INF,sizeof(vis)); // 在每个盆友进行bfs()前初始化
            vis[a[i]][b[i]]=1;
            res=bfs(a[i],b[i]);

            if(res==INF) continue;
            else
            {
                if(res<=Min)
                {
                    Min=res;
                }
            }
        }

        if(Min==INF)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
        else
            printf("%d\n",Min);

    }
    return 0;
}

如果对优先队列 运算符重载里的 > 和 < 不太明白的可以看看这篇博客:https://blog.csdn.net/zzycsx/article/details/47851737

猜你喜欢

转载自blog.csdn.net/LaoXiangQ/article/details/82932820