一、題目描述
輸入樣例:
3 4
0001
0011
0110
輸出樣例:
3 2 1 0
2 1 0 0
1 0 0 1
二、題解
方法一:單源 bfs(超時)
* 分析題意:題目實際要我們求的是每一個 0
到其最近的 1
的曼哈頓距離。我們不必從 0 開始,我們實際上可以從每個 1 開始,每個 1 和自己的距離是 0,然後不斷 bfs 擴展。遇到 0,則將其座標的值改爲當前 cur 點的深度 +1
。
* 暴力方法:對於每一個 0
都用 bfs 求出所有距離自己最近的 1
的距離,然後取其中的最大值。
* 輸入輸出錯誤:
- 如果二維數組 grid 是 int 類型,用
sc.nextInt()
輸入,報錯:java.util.NoSuchElementException
,注意看樣例,樣例中說了,數字之間沒有空格,所以用 nextInt 讀入的將會是 0001,肯定錯了。 - 如果用
System.out.println();
輸出,會因爲輸出數據量過大而造成的超時。- 建議使用
new BufferedWriter(new OutputStreamWriter(System.out))
來輸出較大結果。但使用 Java 中的 IO 流要導java.io.*
以及拋出 IO 異常。
- 建議使用
- 注意:使用
bufferedWriter
的write
方法後,一定要調用flush
才能輸出內容。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Pos {
int x, y;
public Pos(int _x, int _y) {
x = _x;
y = _y;
}
}
final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
private static char[][] grid;
static int[][] B;
static int R, C;
private static int bfs(int x, int y) {
boolean[][] vis = new boolean[R][C];
Queue<Pos> q = new LinkedList<>();
q.add(new Pos(x, y));
vis[x][y] = true;
int depth = 0;
while (!q.isEmpty()) {
int size = q.size();
while (size-- > 0) {
Pos cur = q.poll();
for (int k = 0; k < 4; k++) {
int tx = cur.x + dir[k][0];
int ty = cur.y + dir[k][1];
if (tx >= 0 && tx < R && ty >= 0 && ty < C && !vis[tx][ty]) {
if (grid[tx][ty] == '1') {
return depth + 1;
}
vis[tx][ty] = true;
q.add(new Pos(tx, ty));
}
}
}
depth++;
}
return 0;
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
R = sc.nextInt();
C = sc.nextInt();
grid = new char[R][C];
B = new int[R][C];
for (int i = 0; i < R; i++) {
String s = sc.next();
for (int j = 0; j < C; j++)
grid[i][j] = s.charAt(j);
}
for (int i = 0; i < R; i++)
for (int j = 0; j < C; j++) {
if (grid[i][j] == '0')
B[i][j] = bfs(i, j);
}
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
out.write(B[i][j] + " ");
}
out.write("\n");
}
out.flush();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:多源 bfs
多源 bfs 可以把每一個 1 抽象爲 n 叉樹上的第一層結點,而這一層結點有着許多的孩子,即數字 0。我們要求的是離每一個結點 1 的最遠的結點 0 的最小距離值(bfs 求出來的就是最小值)。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Pos {
int x, y;
public Pos(int _x, int _y) {
x = _x;
y = _y;
}
}
final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
private static char[][] grid;
static int[][] B;
static int R, C;
private static void bfs() {
Queue<Pos> q = new LinkedList<>();
for (int i = 0; i < R; i++)
for (int j = 0; j < C; j++) {
if (grid[i][j] == '1')
q.add(new Pos(i, j));
}
while (!q.isEmpty()) {
int size = q.size();
while (size-- > 0) {
Pos cur = q.poll();
for (int k = 0; k < 4; k++) {
int tx = cur.x + dir[k][0];
int ty = cur.y + dir[k][1];
if (tx >= 0 && tx < R && ty >= 0 && ty < C && grid[tx][ty] == '0') {
grid[tx][ty] = '1';
B[tx][ty] = B[cur.x][cur.y] + 1;
q.add(new Pos(tx, ty));
}
}
}
}
}
// main
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
R = sc.nextInt();
C = sc.nextInt();
grid = new char[R][C];
B = new int[R][C];
for (int i = 0; i < R; i++) {
String s = sc.next();
for (int j = 0; j < C; j++) {
grid[i][j] = s.charAt(j);
}
}
bfs();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
out.write(B[i][j] + " ");
}
out.write("\n");
}
out.flush();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,