洛谷 P1162 填涂颜色【DFS】

题目链接:https://www.luogu.org/problemnew/show/P1162

题目描述

由数字 0 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 1 构成,围圈时只走上下左右 4 个方向。现要求把闭合圈内的所有空间都填写成 2 .例如: 6 ×6 的方阵( n=6 ),涂色前和涂色后的方阵如下:

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

 

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

输入格式: 

每组测试数据第一行一个整数n(1n30) 

接下来 n 行,由 0 和 1 组成的n×n 的方阵。 

方阵内只有一个闭合圈,圈内至少有一个 0 。

输出格式: 

已经填好数字 2 的完整方阵。

输入样例#1:
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
输出样例#1: 
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1 

说明 

1n30

解题分析:
题目要求我们找出图中唯一的由0组成的闭合圈,然后将这个闭合圈中的所有0全部置为2,输出。注意,要将这里的闭合圈和联通块区分,因为这里不仅仅是要求是0的联通块,并且这个联通块的周围必须是由1全包围。

解题的突破口就是要发现,如果某一由0组成的联通块有在边界上的0,那么该连通块必然不可能是闭合圈(因为该0已是边界,不可能被1全包围),所以我们对每一个边界上的0进行深搜,将由他们延伸出来的连通块

全部标记,最后,图中没有标记的0必然属于闭合。

#include <bits/stdc++.h>
using namespace std;

#define RP(i,s,t) for(int i=s;i<=t;i++)
const int N = 35;
int g[N][N],vis[N][N];
int n;
const int dir[][2]={1,0,0,1,-1,0,0,-1};

void dfs(int x,int y){
  vis[x][y]=1;
  for(int k=0;k<4;k++){
    int xx=x+dir[k][0];
    int yy=y+dir[k][1];
    if( xx<1 || xx>n || yy<1 || yy>n || vis[xx][yy] || g[xx][yy]==1 ) continue;
    dfs(xx,yy); 
  }
}


int main(){
  scanf("%d",&n);
  RP(i,1,n) RP(j,1,n) scanf("%d",&g[i][j]);
  RP(i,1,n) RP(j,1,n) {
    if((i==1 || j==1 || i==n || j==n ) && g[i][j]==0) dfs(i,j);
  }

  RP(i,1,n){ 
    RP(j,1,n) {
    if( g[i][j]==0 && !vis[i][j] ) g[i][j]=2;
    printf("%d ",g[i][j]);
    }
    puts("");
  }
}

 


posted @ 2018-05-30 21:25  悠悠呦~  阅读(247)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end