位图

32. [POI1999] 位图

★   输入文件: bit.in   输出文件: bit.out    简单对比
时间限制:1 s   内存限制:128 MB

【问题描述 】

给定一个 n*m 的矩形位图,位图中的每个像素不是白色就是黑色,但至少有一个是白色的。第 i 行、第 j 列的像素被称作像素 (i, j) 。两个像素 p1 = (i1, j1) , p2 = (i2, j2) 之间的距离定义为: d(p1, p2) = |i1 - i2| + |j1 - j2|.

【任务 】

编一个程序完成以下操作:

1 .从输入文件中读入此位图的有关信息。

2 .对于每个像素,计算此像素与离其最近的“白像素”的距离。

3 .将结果写到输出文件里面。

【输入格式 】

输入文件的第一行包含两个整数 n, m ( 1 ≤ n ≤ 182, 1 ≤ m ≤ 182 ),用一个空格隔开。接下来 n 行,每一行都包含一个长度为 m 的 01 串;第 i+1 行,第 j 列的字符若为 1 ,则像素 (i, j) 是白色的;否则是黑色的。

【输出格式 】

输出文件包含 n 行 , 每行有 m 个用空格隔开的整数。第 i 行、第 j 列的整数表示 (i, j) 与离它最近的白像素之间的距离

【样例输入】

bit.in

3 4 
0001 
0011 
0110

【样例输出】

bit.out

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

简单BFS+DP,直接以白色点向外拓展,只有下个节点是黑色点且 所得距离小于以前搜索到这个点的距离。

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200;
char map[maxn][maxn];
bool vis[maxn][maxn];
int dp[maxn][maxn];
int dx[]={0,1,-1,0};
int dy[]={1,0,0,-1};
int n,m;
bool check(int x,int y){
     return x>=0&&x<n&&y>=0&&y<m;
}
void bfs(int sx,int sy){
    queue<int > q;
    memset(vis,false,sizeof(vis));
    q.push(sx); q.push(sy);
    vis[sx][sy]=true;
    while(!q.empty()){
        int x=q.front();  q.pop();
        int y=q.front();  q.pop();
        for(int i=0;i<4;i++){
            int nx=x+dx[i];  int ny=y+dy[i];
            int s=abs(nx-sx)+abs(ny-sy);
            if(check(nx,ny)&&map[nx][ny]=='0'&&!vis[nx][ny]&&dp[nx][ny]>s){
                 vis[nx][ny]=true;
                 dp[nx][ny]=s;
                 q.push(nx); q.push(ny);
            }
        }
    }
}
int main(){
    freopen("bit.in","r",stdin);
    freopen("bit.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)  scanf("%s",map[i]);
    for(int i=0;i<n;i++) for(int j=0;j<m;j++) dp[i][j]=100000;

    for(int i=0;i<n;i++){
       for(int j=0;j<m;j++)
        if(map[i][j]=='1'){
              dp[i][j]=0;
              bfs(i,j);
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m-1;j++)
        printf("%d ",dp[i][j]);
        printf("%d\n",dp[i][m-1]);
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值