DFS和连通块问题

这个题的难度在于你的思路够不够清晰,或者说是你用的dfs真的够不够熟练

有人可能回想到先放X再判断联通这种思路,这种思路是极其浪费时间的

最好的方法就是先dfs标记一块连通区域,然后剩下k个地方放X,这是最省事的思路,因为dfs和bfs只能爬连通区域,就是利用这一特性,有了这个思路

另外,有了思路之后,我在书写代码的时候,出现了些小错误,我把初始递归的东西拿到了外边,导致递归有点迷,我总结反思之后,决定以后递归的东西都写在里面,系统完整标准的书写代码

Pavel 喜欢网格迷宫。一个网格迷宫是一个 n × m 的长方形迷宫,其中每个单元格要么是空白的,要么是墙体。您可以从一个单元格走到另一个单元格,只要两个单元格均是空白的,且拥有一条公共的边。

Pavel 绘制了一个网格迷宫,包含的全部空白单元格形成了一个连通区域。换言之,您可以从任何一个空白的单元格,走到其它任意的空白单元格。Pavel 的迷宫如果墙体太少,他就不喜欢这个迷宫。他希望将 k 个空白的单元格转换为墙体,使得剩余的全部单元格仍然能够形成一个连通区域。请帮助他实现这个任务。

输入

第一行包含了三个整数 nmk (1 ≤ n, m ≤ 500, 0 ≤ k < s),其中 n 和 m 分别是迷宫的高度和宽度,k 是 Pavel 希望加入的墙体数目,并且字母 s 表示原始迷宫中的空白单元格数目。

接下来的 n 行中,每行包含 m 个字符。它们描述了原始的迷宫。如果某行中的一个字符等于 ".",则相应的单元格为空白;如果字符等于 "#",则单元格为墙体。

输出

打印 n 行,每行包含 m 个字符:符合 Pavel 需求的新迷宫。将已转换为墙体的原始空白单元格标识为 "X";其它单元格必须保留为未更改状态 (也就是 "." 和 "#")。

数据保证:存在一个解决方案。如果有多个解决方案,可输出它们中的任意一个。

示例

输入

3 4 2
#..#
..#.
#...

输出

#.X#
X.#.
#...

输入

5 4 5
#...
#.#.
.#..
...#
.#.#

输出

#XXX
#X#.
X#..
...#
.#.#
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#define MAXN 505
bool book[MAXN][MAXN];
char group[MAXN][MAXN];
int n,m,k;
int sum = 0;
int con;
int Next[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
void dfs(int sx,int sy)
{
        if(!con) return;
        else
        {
            con--;
            book[sx][sy] = true;
            for(int i = 0; i < 4; i++)
            {
                int nowx = sx + Next[i][0];
                int nowy = sy + Next[i][1];
                if(nowx>0&&nowx<=n&&nowy>0&&nowy<=m&&!book[nowx][nowy]&&group[nowx][nowy] == '.')
                {
                    dfs(nowx,nowy);
                }
            }
        }
}
int main()
{
    bool flag = false;
    int sx,sy;
    cin>>n>>m>>k;
    memset(book,0,sizeof(book));
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            cin>>group[i][j];
            if(group[i][j] == '.') sum++;
            if(group[i][j] == '.'&&!flag)
            {
                sx = i;
                sy = j;
                flag = true;
            }
        }
    }
    con = sum - k;
    dfs(sx,sy);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(group[i][j] == '.'&& !book[i][j])
            {
                cout<<'X';
            }
            else cout<<group[i][j];
        }
        cout<<endl;
    }
    return 0;
}

赠AC代码一份,祝见过凌晨四点洛杉矶的人一生平安~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值