这个题的难度在于你的思路够不够清晰,或者说是你用的dfs真的够不够熟练
有人可能回想到先放X再判断联通这种思路,这种思路是极其浪费时间的
最好的方法就是先dfs标记一块连通区域,然后剩下k个地方放X,这是最省事的思路,因为dfs和bfs只能爬连通区域,就是利用这一特性,有了这个思路
另外,有了思路之后,我在书写代码的时候,出现了些小错误,我把初始递归的东西拿到了外边,导致递归有点迷,我总结反思之后,决定以后递归的东西都写在里面,系统完整标准的书写代码
Pavel 喜欢网格迷宫。一个网格迷宫是一个 n × m 的长方形迷宫,其中每个单元格要么是空白的,要么是墙体。您可以从一个单元格走到另一个单元格,只要两个单元格均是空白的,且拥有一条公共的边。
Pavel 绘制了一个网格迷宫,包含的全部空白单元格形成了一个连通区域。换言之,您可以从任何一个空白的单元格,走到其它任意的空白单元格。Pavel 的迷宫如果墙体太少,他就不喜欢这个迷宫。他希望将 k 个空白的单元格转换为墙体,使得剩余的全部单元格仍然能够形成一个连通区域。请帮助他实现这个任务。
输入
第一行包含了三个整数 n, m, k (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代码一份,祝见过凌晨四点洛杉矶的人一生平安~