FZU1408(BFS+优化) 之 位图

 Problem 1408 位图

Accept: 502    Submit: 2281
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

现在我们给出一个n*m的黑白位图,n为行数,m为列数,且该位图中至少含有一个白色的像素。我们用(i,j)来表示第i行第j列的像素,并且定义两像素点p1=(i1,j1)和p2=(i2,j2)之间的距离为:d(p1,p2)=|i1-i2|+|j1-j2|。

对于任意给定的位图,计算出位图中每个像素到与它最近的白色像素之间的距离。

Input

本题有多组输入数据,每组数据第一行包含两个整数n,m,用空格分开,1<=n,m<=182。之后的n行每行包含一个长度为m的由0和1组成的字符串,即第i行第j个字符如果为"1",那么表示像素(i,j)为白的,否则为黑的。

Output

对于每组数据,输出包含n行,第i行的第j个数字为f(i,j),表示像素(i,j)到最近的白色像素的距离。每行内的数字用空格分开。

Sample Input

3 4
0001
0011
0110

Sample Output

3 2 1 0
2 1 0 0
1 0 0 1 



分析:广度优先搜索,刚开始写的代码老师内存超限,看了讨论知道,不能从每个0去找1,而应该从1去找0,这样比较节约内存和时间


memory limit exceed 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=200;

int flag[200][200];
char a[200][200];
int n,m;
int direction[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
int ans[40000],num;

struct point
{
    char value;
    int x,y;
    int step;
};

void bfs(char value,int row,int col,int step)
{
    int x,y;
    point v,w,top;
    v.value=value;
    v.x=row;
    v.y=col;
    v.step=step;
    queue<point> q;
    q.push(v);
    flag[row][col]=step+1;
    while(!q.empty())
    {
        top=q.front(); q.pop();
        if(top.value=='1')
        {
            ans[num]=top.step;
            num++;
            break;
        }
        for(int i=0;i<4;i++)
        {
            x=top.x+direction[i][0];
            y=top.y+direction[i][1];
            if(x>=0 && x<n && y>=0 && y<m && !flag[x][y])
            {
                w.value=a[x][y];
                w.x=x;
                w.y=y;
                w.step=top.step+1;
                q.push(w);
            }
        }
    }
}

int main()
{
    while(cin>>n>>m)
    {
        num=0;
        memset(ans,0,sizeof(ans));
        for(int i=0; i<n; i++)
            scanf("%s",a[i]);

        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(a[i][j]=='1')
                {
                    ans[num]=0;
                    num++;
                }
                else
                {
                    memset(flag,0,sizeof(flag));
                    bfs(a[i][j],i,j,0);
                }
            }
        }

        for(int i=0; i<num; i++)
        {
            cout<<ans[i];
            if((i+1)%m==0) cout<<endl;
            else cout<<" ";
        }
    }
    return 0;
}



AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=200;

int flag[200][200];
char a[200][200];
int n,m;
int direction[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
int ans[200][200];

struct point
{
    char value;
    int x,y;
    int step;
};

queue<point> q;

void bfs()
{
    while(!q.empty())
    {
        point top=q.front(); q.pop();
        for(int i=0;i<4;i++)
        {
            int x=top.x+direction[i][0];
            int y=top.y+direction[i][1];
            if(x>=0 && x<n && y>=0 && y<m && !flag[x][y])
            {
                flag[x][y]=1;
                ans[x][y]=top.step+1;
                point w;
                w.value=a[x][y];
                w.x=x;
                w.y=y;
                w.step=top.step+1;
                q.push(w);
            }
        }
    }
}

int main()
{
    while(cin>>n>>m)
    {
        point cur;
        memset(ans,0,sizeof(ans));
        memset(flag,0,sizeof(flag));
        for(int i=0; i<n; i++)
            scanf("%s",a[i]);

        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(a[i][j]=='1')
                {
                    flag[i][j]=1;
                    ans[i][j]=0;
                    cur.value='1';
                    cur.x=i;
                    cur.y=j;
                    cur.step=0;
                    q.push(cur);
                }
            }
        }
        bfs();
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                cout<<ans[i][j];
                if(j!=m-1) cout<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值