Rescue(bfs+优先队列)

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


题意:在一个迷宫里,天使angle被困于内,但是天使有朋友friends帮忙,那么问题来了,天使的朋友是否能救出天使,如果能救出,那么最短的时间是多少???假设每移动一格需要1单位时间,在这个迷宫之中有个叫x的守卫,天使的朋友们要干掉这些守卫来救天使,如果有必要的话.而干掉守卫又需要1单位时间.

所以,现在的问题就是天使的朋友们救天使的最短时间是多少.???

分析:这个迷宫还是往常的迷宫,有墙,有目的地,有出发点.

按照题意来,我们通常会想,从r来搜索a,然后比较得到最短的距离.但是呢,整个地图里,r(朋友)不止一个,比较来比较去比较麻烦.但是a(天使)有且仅有一个,那么不妨从a开始遍历图来搜索r 每次扩展搜索,耗时加一,如果有x那么耗时再加一,然后,第一个找到的r的耗时,即最短的耗时

按照这思路,一个自然而然的bfs队列方法就出来了...

请看代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define M 205
char mm[M][M];
int n,m;
int vis[M][M];
int ne[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
struct node
{
    int x;
    int y;
    int time;
};
queue<node> q;
struct node p;
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(vis,0,sizeof(vis));
        memset(mm,'\0',sizeof(mm));
        for(int i=0; i<n; i++)
        {
            scanf("%s",mm[i]);
            for(int j=0; j<m; j++)
            {
                if(mm[i][j]=='a')
                {
                    p.x=i;
                    p.y=j;
                    p.time=0;
                    q.push(p);
                    vis[i][j]=1;
                }
            }
        }
        int flag=0;
        while(!q.empty())
        {
            node nn=q.front();
            q.pop();
//            for(int i=0;i<n;i++)
//            {
//                for(int j=0;j<m;j++)
//                    printf("%d ",vis[i][j]);
//                printf("\n");
//            }
//            printf("\n");
            if(mm[nn.x][nn.y]=='r')
            {
                flag=1;
                printf("%d\n",nn.time);
                break;
            }
            for(int i=0; i<4; i++)
            {
                node New;
                New.x=nn.x+ne[i][0];
                New.y=nn.y+ne[i][1];
                if(New.x>=0&&New.x<n&&New.y>=0&&New.y<m&&mm[New.x][New.y]!='#'&&!vis[New.x][New.y])
                {
                    vis[New.x][New.y]=1;
                    New.time=nn.time+1;
                    if(mm[New.x][New.y]=='x')
                        New.time+=1;
                    q.push(New);
                }
            }
        }
        if(!flag)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
    }
    return 0;
}

代码也打出来了,样例也过了,那么一提交就wa了

那么是为什么呢...试试下面这个样例就知道了

6 6

axxxxr

. . . . . .

. . . . . . 

. . . . . .

. . . . . . 

. . . . . .

如果按照普通队列来执行,那么他会输出9

但实际上我们来看其实并不是9,而是7.

这是因为他没有考虑耗时大小,在队列中只是一味按照四个扩展方向在固执的搜索.


那么要怎么做才能避免这个问题呢.???

下面看 分析

我们说了,上面代码他没有考虑耗时大小,只是一味搜索.

那么我们要做的就是让他考虑,让耗时小的先扩展,先搜索,把耗时大的放在后面.

那么这个就是优先队列的思想了.


既然知道是优先队列了.那么请看下面博客,相信我,如果你能打出上面的代码,那么看完下面这篇大佬的博客,

你也能打出优先队列的代码

https://www.cnblogs.com/xzxl/p/7266404.html

如果看完了,你可以自己试试看,不一定要看我的代码,相信你自己.



这便是优先队列+bfs

:

请看代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define M 205
char mm[M][M];
int n,m;
int vis[M][M];
int ne[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
struct node
{
    int x;
    int y;
    int time;
    friend bool operator <(node a,node b)
    {
        return a.time>b.time;
    }
};
priority_queue<node> q;
struct node p;
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(vis,0,sizeof(vis));
        memset(mm,'\0',sizeof(mm));
        for(int i=0; i<n; i++)
        {
            scanf("%s",mm[i]);
            for(int j=0; j<m; j++)
            {
                if(mm[i][j]=='a')
                {
                    p.x=i;
                    p.y=j;
                    p.time=0;
                    q.push(p);
                    vis[i][j]=1;
                }
            }
        }
        int flag=0;
        while(!q.empty())
        {
            node nn=q.top();
            q.pop();
//            for(int i=0;i<n;i++)
//            {
//                for(int j=0;j<m;j++)
//                    printf("%d ",vis[i][j]);
//                printf("\n");
//            }
//            printf("\n");
            if(mm[nn.x][nn.y]=='r')
            {
                flag=1;
                printf("%d\n",nn.time);
                break;
            }
            for(int i=0; i<4; i++)
            {
                node New;
                New.x=nn.x+ne[i][0];
                New.y=nn.y+ne[i][1];
                if(New.x>=0&&New.x<n&&New.y>=0&&New.y<m&&mm[New.x][New.y]!='#'&&!vis[New.x][New.y])
                {
                    vis[New.x][New.y]=1;
                    New.time=nn.time+1;
                    if(mm[New.x][New.y]=='x')
                        New.time+=1;
                    q.push(New);
                }
            }
        }
        if(!flag)
            printf("Poor ANGEL has to stay in the prison all his life.\n");
    }
    return 0;
}

ps:2018-04-18 23:24:47

哈哈 白天刷题晚上写博客还是挺有意思的,初接触优先队列,看着还挺有意思的.哈哈

虽然寝室熄灯早,但是今天扛着熄了灯也要写完的信念.

从一开始不知所措学算法,后来为了名利学算法,再后来,为了喜欢,为了自己想学而学

现在的我真正的感到了快乐,虽然有时会被自己笨到崩溃,会被其他人写的博客坑到死,也不能怪他们,好多博客都是好几年的前的了,

话这么说,可能等我博客浏览高了,我也成为过去了


愿你为了学习而学习,愿你在学习中找到快乐.

希望我们能早点苦尽甘来.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值