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#..
...#
.#.#
X
,可保证图中的 .
仍是连通的。import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int N, M, k;
static char[][] grid;
static boolean[][] vis;
final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
static boolean inArea(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < M;
}
static void dfs(int x, int y) {
for (int k = 0; k < 4; k++) {
int tx = x + dir[k][0];
int ty = y + dir[k][1];
if (!inArea(tx, ty) || grid[tx][ty] != '.' || vis[tx][ty]) {
continue;
}
vis[tx][ty] = true;
dfs(tx, ty);
}
if (k > 0) {
grid[x][y] = 'X';
k--;
}
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
N = sc.nextInt();
M = sc.nextInt();
k = sc.nextInt();
grid = new char[N][M];
vis = new boolean[N][M];
for (int i = 0; i < N; i++) {
String s = sc.next();
for (int j = 0; j < M; j++)
grid[i][j] = s.charAt(j);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (grid[i][j] == '.')
dfs(i, j);
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(grid[x][y]);
}
System.out.println();
}
}
}
进阶:如果题目不保证找得到答案,你该如何处理本问题?
我的做法是:对网格进行一次 bfs,判断是否存在一个大小至少为n*m-k
的连通块,并标记连通块,最后再次遍历网格,将没有标记的.
当做X
即可。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int N, M, k;
static char[][] grid;
static boolean[][] vis;
final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
static int cnt, sum, diff;
static boolean inArea(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < M;
}
static void bfs(int x, int y) {
Queue<int[]> q = new ArrayDeque<>();
q.add(new int[] {x, y});
vis[x][y] = true;
cnt = 1;
while (!q.isEmpty()) {
int[] t = q.poll();
for (int k = 0; k < 4; k++) {
int tx = t[0] + dir[k][0];
int ty = t[1] + dir[k][1];
if (!inArea(tx, ty))
continue;
if (grid[tx][ty] == '.' && !vis[tx][ty]) {
if (cnt == diff) {
return;
}
q.add(new int[]{tx, ty});
vis[tx][ty] = true;
cnt++;
}
}
}
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
N = sc.nextInt();
M = sc.nextInt();
k = sc.nextInt();
grid = new char[N][M];
vis = new boolean[N][M];
int sx = -1, sy = -1;
for (int i = 0; i < N; i++) {
String s = sc.next();
for (int j = 0; j < M; j++) {
grid[i][j] = s.charAt(j);
if (grid[i][j] == '.') {
sum++;
sx = i; sy = j;
}
}
}
if (sx == -1 && sy == -1) {
System.out.println(-1);
return;
}
diff = sum - k;
bfs(sx, sy);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (vis[i][j] && grid[i][j] == '.') {
System.out.print('.');
} else if (!vis[i][j] && grid[i][j] == '.') {
System.out.print('X');
} else {
System.out.print('#');
}
}
System.out.println();
}
}
}