洛谷P1162 填涂颜色(DFS漫水填充法)

2 篇文章 0 订阅
 

洛谷P1162 填涂颜色(DFS漫水填充法)

题目描述

由数字 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(1 \le n \le 30)n(1≤n≤30)

接下来 nn 行,由 00 和 11 组成的 n \times nn×n 的方阵。

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

//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)

输出格式

已经填好数字 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

说明

1<=n<=30

 

思路

在方阵内只有一个闭合圈,也就意味着除了被包围的那些0连通块,其余0连通块都与方阵边界有接触,

先对所有0连通块floodfill预先涂色,每个不同的值为0的连通块都被替换成-1,-2,-3...如下图

再遍历边界,找出并标记与边界有接触的0连通块

 int temp[maxN];
    memset(temp,0,sizeof(temp));
    for(int i=1;i<=n;i++)
    {
        if(maze[1][i]<0)
        {
            temp[-maze[1][i]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[i][1]<0)
        {
            temp[-maze[i][1]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[n][i]<0)
        {
            temp[-maze[n][i]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[i][n]<0)
        {
            temp[-maze[i][n]]=1;
        }
    }

最后输出时判断是否是边界上的0,又是否是1即可

代码

#include<bits/stdc++.h>
using namespace std;
const int maxN=35;
int maze[maxN][maxN];
int book[maxN][maxN];
int tX,tY;
int n;
/*void Move(int x)
{
    if(x==1) { tX=x+1;tY=y; }
    if(x==2) { tX=x-1;tY=y; }
    if(x==3) { tX=x;tY=y+1; }
    if(x==4) { tX=x;tY=y-1; }
}*/
void DFS(int x,int y,int color)
{
    maze[x][y]=color;
    for(int k=1;k<=4;k++)
    {
        if(k==1) { tX=x+1;tY=y; }
        if(k==2) { tX=x-1;tY=y; }
        if(k==3) { tX=x;tY=y+1; }
        if(k==4) { tX=x;tY=y-1; }
        if(tX<1||tX>n||tY<1||tY>n) continue;
        if(maze[tX][tY]==0&&book[tX][tY]==0)
        {
            book[tX][tY]=1;
            DFS(tX,tY,color);
        }
    }
    return;
}
​
int main()
{
    int num=0;
    memset(maze,0,sizeof(maze));
    memset(book,0,sizeof(book));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&maze[i][j]);
​
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(maze[i][j]==0)
            {
                num--;
                book[i][j]=1;
                DFS(i,j,num);
            }
        }
    }
    printf("变为\n");
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%3d",maze[i][j]);
        }
        printf("\n");
    }
​
​
    int temp[maxN];
    memset(temp,0,sizeof(temp));
    for(int i=1;i<=n;i++)
    {
        if(maze[1][i]<0)
        {
            temp[-maze[1][i]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[i][1]<0)
        {
            temp[-maze[i][1]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[n][i]<0)
        {
            temp[-maze[n][i]]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(maze[i][n]<0)
        {
            temp[-maze[i][n]]=1;
        }
    }
​
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(maze[i][j]==1)
            {
                printf("1");
                if(j!=n) printf(" ");
            }
            else if(temp[-maze[i][j]]==1)
            {
                printf("0");
                if(j!=n) printf(" ");
            }
            else
            {
                printf("2");
                if(j!=n) printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值