算法实践:公主的攻击范围

公主的攻击范围

描述

塞尔达公主瘦弱的身体里面蕴含着不可思议的神圣力量,这个力量从公主所在的位置释放,可以逐层扩散到加农污秽掌控的区域。

给定一个N行M列的区域,代号为1的区域是公主能力释放的初始区,代号为0的区域表示需要洁净的区域。

每经过1毫秒,公主的神圣之光向外扩散一格,洁净相邻区域(4个方向),请计算每个标记为0的区域中加农的势力最多还能得瑟几毫秒。

格子与格子之间的距离使用曼哈顿距离计算。

给定一个N行M列的01矩阵A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为:

dist(A[i][j],A[k][l])=|i-k|+|j-l|
输出一个N行M列的整数矩阵B,其中:
 B[i][j]=min_{1≤x≤N,1≤y≤M,A[x][y]=1}⁡{dist(A[i][j],A[x][y])}

根据如上公式可知:曼哈顿距离指两点之间的行坐标i距离和列坐标j距离之和。

题目的意思就是求出矩阵中所有节点为0的点,到节点为1的点的曼哈顿距离。

输入

第一行两个整数n,m。

接下来一个N行M列的01矩阵,数字之间没有空格。

数据范围:

1≤N,M≤1000

输出

一个N行M列的矩阵B,相邻两个整数之间用一个空格隔开。每个整数表示加农势力存在的毫秒数(最小曼哈顿距离值)

输入样例

3 4
0001
0011
0110

输出样例

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

难度

高,BFS

题解

把所有的1的点设置为源点(多源点)

转化为多源点广搜问题

代码

#include<bits/stdc++.h>
using namespace std;
//定义方向向量
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
const int N=1010;
//战斗区域
char g[N][N];
//计算从1的点出发抵达每个0的最短距离
int d[N][N],n,m;
//pair类型变量保存x,y
typedef pair<int,int> PII;
queue<PII>q;  //BFS使用的队列

//读入数据
void Build(int n,int m){
    memset(d,-1,sizeof(d));
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            char c = getchar();
            while (c!='0' && c!='1'){
                c = getchar();
            }
            if(c=='1'){
                d[i][j]=0;
                q.push(make_pair(i,j));  //压入队列,多源广搜
            }
        }
}
//输出
void Print(int n,int m){
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++) cout<<d[i][j]<<' ';
        cout<<endl;
    }
}

void bfs(){
    while(q.size()){  
        auto t=q.front();
        q.pop();

        int x=t.first,y=t.second;
        for(int i=0;i<4;i++){
            int a=x+dx[i],b=y+dy[i];
            if(a>=0 && a<n && b>=0&&  b<m && d[a][b]==-1){  //判断是否合法
                d[a][b]=d[x][y]+1;
                q.push({a,b});
            }
        }
    }
}

int main(void){
    cin>>n>>m;
    Build(n,m);
    bfs();
    Print(n,m);
    return 0;    
}
原创文章 153 获赞 208 访问量 2万+

猜你喜欢

转载自blog.csdn.net/matafeiyanll/article/details/105855491
今日推荐