【bfs】B019_矩陣距離(單源 bfs | 多源 bfs)

一、題目描述

在這裏插入圖片描述

輸入樣例:
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 異常。
  • 注意:使用 bufferedWriterwrite 方法後,一定要調用 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();
    }
}

複雜度分析

  • 時間複雜度:O(R×C×cnt0)O(R × C × cnt0)
  • 空間複雜度:O(R×C)O(R × C)

方法二:多源 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();
    }
}

複雜度分析

  • 時間複雜度:O(R×C)O(R × C)
  • 空間複雜度:O(R×C)O(R × C)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章