抠图(DFS)

蒜头君在做图像处理的项目时,遇到了一个问题。他需要摘取出图片中,某个黑色线框内的图片,现在请你来帮助他完成这一步,把黑色线框外的区域全部变为黑色,即只保留黑色线框内的颜色

抠图(DFS)

蒜头君可能同时摘取多个线框,这些线框不会出现相邻,相交,包含关系,因为选择线框太多,所以蒜头君可能把其中一部分的线框少画一条边,所以这种线框是无效的。

已知图中除了黑线上的点外,图像中没有纯黑色(即像素为 00 的点)。

矩形关系说明:

抠图(DFS)

其中下面的数据也属于相邻。

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

也就是说 00 的周围(八个方向),不会有另外一个矩形的 00。

输入格式

第一行输入测试数据的组数 N(0 < N \le 10)N(0<N≤10)。

每组测试数据的第一行是两个整数 H,WH,W 分别表示图片的高度和宽度 (3 \le H,W \le 500)(3≤H,W≤500)。

随后的 HH 行,每行有 WW 个正整数,表示该点的像素值。(像素值都在 00 到 255255 之间,00 表示黑色,255255 表示白色),每行整数之间使用'\t'隔开。

输出格式

以矩阵形式输出,先把黑色框之外的区域变黑,然后输出图像中各点的像素值。

数据约定

对于 30\%30% 的数据,线框是宽度为 11 的矩形,并且线框都是完整的。

对于 60\%60% 的数据,线框是宽度不固定的的矩形,并且线框都是完整的。

对于 100\%100% 的数据,线框可能有多个(题目保证线框不会出现相邻,相交,包含关系),线框是宽度不固定,有部分线框可能缺失其中的一条边(可以认为这种线框为无效线框)。

样例解释

对于第一组数据:

这是一个完整的矩形,所以会保留线框内的颜色,保留下 (3,2),(3,3)(3,2),(3,3) 的像素值。

对于第二组数据:

只有一个矩形,这个矩形不是完成整的矩形,所有是无效线框,所以没有像素值被保留。

对于第三组数据:

有多个矩形,且矩形都满足不相邻,相交,包含的关系。

样例输入复制

3
4 5
1	0	0	0	1
1	0	1	0	1
1	0	1	0	1
1	0	0	0	1
5 6
1	1	1	1	1	1
1	0	1	0	1	1
1	0	1	0	1	1
1	0	0	0	1	1
1	1	1	1	1	1
10 10
1	1	1	1	1	1	1	1	1	1
1	0	0	0	0	0	1	0	1	0
1	0	0	0	0	0	1	0	1	0
1	0	0	1	0	0	1	0	0	0
1	0	0	0	0	0	1	1	1	1
1	0	0	0	0	0	1	1	1	1
1	1	1	1	1	1	1	1	1	1
1	1	1	0	0	0	1	0	0	0
1	1	1	0	1	0	1	0	1	0
1	1	1	0	0	0	1	0	0	0

样例输出复制

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

题目来源

2019 蓝桥杯省赛 B 组模拟赛(一)

解析:

从四周找连通块,对于不完整的长方体,自然能把里面的给变成0,用dfs或者bfs都可以

注意大于0就是白色,不仅仅是1

ac:

#include<bits/stdc++.h>
#define MAXN 505
using namespace std;
int tx[4]={0,1,0,-1};
int ty[4]={1,0,-1,0};

int n,m;
int mp[MAXN][MAXN];
int vis[MAXN][MAXN];

void dfs(int x,int y)
{
    mp[x][y]=0;
    for(int i=0;i<4;i++)
    {
        int dx=x+tx[i];
        int dy=y+ty[i];
        if(dx>=0&&dy>=0&&dx<n&&dy<m)
            if(mp[dx][dy]>0)
                dfs(dx,dy);
    }
}

int main()
{
    //freopen("E:/in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));

        scanf("%d%d",&n,&m);

        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                scanf("%d",&mp[i][j]);

        for(int i=0;i<m;i++)
        {
            if(mp[0][i]>0)
                dfs(0,i);
            if(mp[n-1][i]>0)
                dfs(n-1,i);
        }

        for(int i=0;i<n;i++)
        {
            if(mp[i][0]>0)
                dfs(i,0);
            if(mp[i][m-1]>0)
                dfs(i,m-1);
        }

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