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代码一份,祝见过凌晨四点洛杉矶的人一生平安~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里汇集了浙江大学一些同学的算法,列表如下: 几何\ 多边形 多边形切割 浮点函数 几何公式 面积 球面 三角形 三维几何 凸包(graham) 网格(pick) 圆 整数函数 注意 结构\ 并查集 并查集扩展(friend_enemy) 堆(binary) 堆(mapped) 矩形切割 线段树 线段树扩展 线段树应用 子段和 子阵和 其他\ 大数(整数类封装) 分数 矩阵 线性方程组(gauss) 日期 线性相关 数论\ 阶乘最后非零位 模线性方程(组) 质数表 质数随机判定(miller_rabin) 质因数分解 最大公约数欧拉函数 数值计算\ 定积分计算(Romberg) 多项式求根(牛顿法) 周期性方程(追赶法) 图论_NP搜索\ 最大团(n小于64) 最大团 图论_连通性\ 无向图关键边(dfs邻接阵形式) 无向图关键点(dfs邻接阵形式) 无向图(bfs邻接阵形式) 无向图连通分支(bfs邻接阵形式) 无向图连通分支(dfs邻接阵形式) 有向图强连通分支(bfs邻接阵形式) 有向图强连通分支(dfs邻接阵形式) 有向图最小点基(邻接阵形式) 图论_匹配\ 二分图最大匹配(hungary邻接表形式) 二分图最大匹配(hungary邻接阵形式) 二分图最大匹配(hungary邻接表形式,邻接阵接口) 二分图最大匹配(hungary正向表形式) 二分图最佳匹配(kuhn_munkras邻接阵形式) 一般图最大匹配(邻接表形式) 一般图最大匹配(邻接阵形式) 一般图最大匹配(正向表形式) 一般图匹配(邻接表形式,邻接阵接口) 图论_网络流\ 上下界最大流(邻接阵形式) 上下界最小流(邻接阵形式) 上下界最大流(邻接表形式) 上下界最小流(邻接表形式) 最大流(邻接阵形式) 最大流(邻接表形式) 最大流(邻接表形式,邻接阵接口) 最大流无流量(邻接阵形式) 最小费用最大流(邻接阵形式) 图论_应用\ 欧拉回路(邻接阵形式) 前序表转化 树的优化算法 拓扑排序(邻接阵形式) 最佳边割集 最佳顶点割集 最小边割集 最小顶点割集 最小路径覆盖 图论_最短路径\ 最短路径(单源bellman_ford邻接阵形式) 最短路径(单源dijkstra邻接阵形式) 最短路径(单源dijkstra_bfs邻接表形式) 最短路径(单源dijkstra_bfs正向表形式) 最短路径(单源dijkstra+binary_heap邻接表形式) 最短路径(单源dijkstra+binary_heap正向表形式) 最短路径(单源dijkstra+mapped_heap邻接表形式) 最短路径(单源dijkstra+mapped_heap正向表形式) 最短路径(多源floyd_warshall邻接阵形式) 图论_支撑树\ 最小生成树(kruskal邻接表形式) 最小生成树(kruskal正向表形式) 最小生成树(prim邻接阵形式) 最小生成树(prim+binary_heap邻接表形式) 最小生成树(prim+binary_heap正向表形式) 最小生成树(prim+mapped_heap邻接表形式) 最小生成树(prim+mapped_heap正向表形式) 最小树形图(邻接阵形式) 应用\ joseph模拟 N皇后构造解 布尔母函数 第k元素 幻方构造 模式匹配(kmp) 逆序对数 字符串最小表示 最长公共单调子序列 最长子序列 最大子串匹配 最大子段和 最大子阵和 组合\ 排列组合生成 生成gray码 置换(polya) 字典序全排列 字典序组合 组合公式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值