POJ 2920 Mine Map(BFS)

POJ 2920 Mine Map(BFS)

http://poj.org/problem?id=2920

题意:

        有一个n*n(n为奇数)的网格金库,金库中有地雷和空格,你从金库的正中间出发,首先如果你所在的当前格子的8个方向附近有地雷.那么你就不能走了,且标记你的当前格子为’#’.如果8方向没地雷,你就把这8方向的格子都走一遍,且标记着8个格子为’.’ . 按照这个规则走过所有你能走的格子上去,并标记好.注意:地雷格子一开始就标记好为’*’.

分析:

        初始化一个map[n][n]=”??????...???”.然后用BFS从中间开始走,按照题意的规则标记且走格入队列即可.

        不过注意:此题是8反向都可以走.

        注意:如果我们走到了一个格子上,这个格子就可能为’.’或者为’#’.取决于这个格子周围是否有地雷,如果有地雷,那么这个格子就是’#’,如果枚地雷,这个格子就是’.’.

        任何我们没走过的格子只能是’*’ ‘?’.

        且如果一个格子已经是’.’’#’,我们就不能再走上去了.也就是说我们只能走到那些’?’的格子上,然后判断出’?’格子的属性,如果’?’格子变成了’#’,那么我们就不能向8个方向扩展,如果’?’格子变成了’.’我们就必须向8个方向扩展.

AC代码:(本代码还能更快,因为我每次判断当前格子8向是否有雷使用了一个循环判断的,其实可以在读入地雷的时候就将它附近的格子cnt[nr][nc]值++,只要map[i][j]==?且cnt[i][j]>0的格子,那么这个格子周围一定有地雷.)

<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=300+5;
struct Node
{
    int r,c;
    Node(int r,int c):r(r),c(c){}
};
int dr[]={-1,1,0,0,-1,1,-1,1};//上下左右,左上,左下,右上,右下
int dc[]={0,0,-1,1,-1,-1,1,1};
char map[maxn][maxn];
int n,m;//n*n网格,m个地雷
bool mine(int r,int c)        //如果r,c格周围有地雷,返回true
{
    for(int d=0;d<8;d++)
    {
        int nr=r+dr[d], nc=c+dc[d];
        if(nr>=1&&nr<=n&&nc>=1&&nc<=n&&map[nr][nc]=='*') return true; //错误,这里nr,nc没有做越界判断
    }
    return false;
}
void BFS(int mr,int mc)
{
    queue<Node> Q;                                           //错误,这里多了一句Q.push语句
    if(mine(mr,mc)) map[mr][mc]='#';
    else map[mr][mc]='.';
    if(map[mr][mc]=='.') Q.push(Node(mr,mc));
    while(!Q.empty())
    {
        Node node=Q.front();Q.pop();//取出来的格子表示已经走到的格子且是'.'的格子
        int r=node.r,c=node.c;
        for(int d=0;d<8;d++)
        {
            int nr=r+dr[d];
            int nc=c+dc[d];
            if(nr>=1&&nr<=n&&nc>=1&&nc<=n&&map[nr][nc]=='?')
            {
                if(mine(nr,nc)) map[nr][nc]='#';            //错误,写成了min(r,c)
                else map[nr][nc]='.';
                if(map[nr][nc]=='.') Q.push(Node(nr,nc));
            }
        }
    }
}
int main()
{
    int T;scanf("%d",&T);
    for(int kase=1;kase<=T;kase++)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                map[i][j]='?';
        while(m--)
        {
            int r,c;
            scanf("%d%d",&r,&c);
            map[r][c]='*';
        }
        BFS((n+1)/2,(n+1)/2);                     //错误,这里写成了(n+1)/2了
        printf("Scenario #%d:\n",kase);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                printf("%c",map[i][j]);
            printf("\n");
        }
        puts("");
    }
    return 0;
}
</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值