水陆距离 (广搜结构体队列)

给定一个N x M的01矩阵,其中1表示陆地,0表示水域。对于每一个位置,求出它距离最近的水域的距离是多少。  

矩阵中每个位置与它上下左右相邻的格子距离为1。

Input

第一行包含两个整数,N和M。

以下N行每行M个0或者1,代表地图。

数据保证至少有1块水域。

对于30%的数据,1 <= N, M <= 100  

对于100%的数据,1 <= N, M <= 800

Output

输出N行,每行M个空格分隔的整数。每个整数表示该位置距离最近的水域的距离。

Sample Input
4 4  
0110  
1111  
1111  
0110
Sample Output
0 1 1 0  
1 2 2 1  
1 2 2 1  
0 1 1 0

    
    分析:题目其实很容易理解.就是给一个N*M的矩阵.然后把除了0之外的点的值变成与其最近0的距离.
            可能我头脑比较清奇.瞬间想到暴力:把每个0存下来,然后遍历每个非零点 然后比较取最小值(于是成功T了.)奈斯???


    再分析:还是从0出发.可以发现这个值是从零周围扩散出去的.那么不难发现,这其实就是个bfs.

        不错,是个bfs,从0的四个方向出发,然后再从扩展的四个方向出发,每次扩展,距离都+1.


思路:边输入边记录0的位置,然后对其初始化,存入队列.

接着,就是经典while循环从0扩散四个方向走队列了.


说的不太好,详情看代码注释.

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<queue>
#define M 805
using namespace std;
struct node
{
    int x;
    int y;
    int dis;
};
struct node p;
string mm[M];
queue<node> q;
int n,m,vis[M][M],ans[M][M],ne[4][2]={0,1,1,0,0,-1,-1,0};
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>mm[i];//这里要注意一下样例输入点中间没空格...
        for(int j=0;j<m;j++)
        {
            if(mm[i][j]=='0')
            {
                vis[i][j]=1;//标记0
                p.x=i;//记录二维点
                p.y=j;
                p.dis=0;
                q.push(p);//入队列.
                ans[i][j]=0;//初始化0点的距离.这个倒是无所谓.
            }
        }
    }
    while(!q.empty())
    {
        p=q.front();//取队首给p进行操作.
        q.pop();//然后把队首弹出.

        int x,y,xx,yy;//这里定义两个变量.
        x=p.x;
        y=p.y;
        p.dis++;//每次队列更新一次,就是说一个点的四方方向结束遍历后.就是说向外扩散一圈后,距离就要+1

        for(int i=0;i<4;i++)//遍历四个方向.
        {
            xx=x+ne[i][0];//先存储一下试试看
            yy=y+ne[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy])//如果没越界并且没走过.
            {
                vis[xx][yy]=1;//标记走过了
                p.x=xx;//存储下一个方向的点
                p.y=yy;
                ans[xx][yy]=p.dis;//满足if 那么更新点距离值.
                q.push(p);//把存储的方向点放入队尾.
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
            cout<<ans[i][j]<<" ";
        cout<<endl;
    }
}

ps:wawawa2018年4月12日 11:04:23 

暴力死T,广搜不会.花了一天来学用队列和广搜.   

原来看过啊哈算法讲的广搜,现在觉得里面太基础太详细,所有的标准模版库里的容器函数都是用数组来模拟的. 

虽然给人讲的很详细,但也只适合学基础,实用的话到不可能再用数组来模拟了.

这里推荐一本书<<算法笔记>>

个人觉得实用,虽然没有<<啊哈算法>>写的那么生动形象,也没有那么基础,但是讲的真的很实用,

怎么说呢,比较综合吧.适合有基础的看.

(滑稽脸)会有人看这个博客嘛..还推荐书...搞笑了...

因为渴望知识而学习,非名利.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值