|
|
|
|
package class18;
|
|
|
|
|
|
|
|
|
|
// 本题测试链接 : https://leetcode.com/problems/shortest-bridge/
|
|
|
|
|
public class Code02_ShortestBridge {
|
|
|
|
|
|
|
|
|
|
public static int shortestBridge(int[][] m) {
|
|
|
|
|
int N = m.length;
|
|
|
|
|
int M = m[0].length;
|
|
|
|
|
int all = N * M;
|
|
|
|
|
int island = 0;
|
|
|
|
|
int[] curs = new int[all];
|
|
|
|
|
int[] nexts = new int[all];
|
|
|
|
|
int[][] records = new int[2][all];
|
|
|
|
|
for (int i = 0; i < N; i++) {
|
|
|
|
|
for (int j = 0; j < M; j++) {
|
|
|
|
|
if (m[i][j] == 1) { // 当前位置发现了1!
|
|
|
|
|
// 把这一片的1,都变成2,同时,抓上来了,这一片1组成的初始队列
|
|
|
|
|
// curs, 把这一片的1到自己的距离,都设置成1了,records
|
|
|
|
|
int queueSize = infect(m, i, j, N, M, curs, 0, records[island]);
|
|
|
|
|
int V = 1;
|
|
|
|
|
while (queueSize != 0) {
|
|
|
|
|
V++;
|
|
|
|
|
// curs里面的点,上下左右,records[点]==0, nexts
|
|
|
|
|
queueSize = bfs(N, M, all, V, curs, queueSize, nexts, records[island]);
|
|
|
|
|
int[] tmp = curs;
|
|
|
|
|
curs = nexts;
|
|
|
|
|
nexts = tmp;
|
|
|
|
|
}
|
|
|
|
|
island++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int min = Integer.MAX_VALUE;
|
|
|
|
|
for (int i = 0; i < all; i++) {
|
|
|
|
|
min = Math.min(min, records[0][i] + records[1][i]);
|
|
|
|
|
}
|
|
|
|
|
return min - 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当前来到m[i][j] , 总行数是N,总列数是M
|
|
|
|
|
// m[i][j]感染出去(找到这一片岛所有的1),把每一个1的坐标,放入到int[] curs队列!
|
|
|
|
|
// 1 (a,b) -> curs[index++] = (a * M + b)
|
|
|
|
|
// 1 (c,d) -> curs[index++] = (c * M + d)
|
|
|
|
|
// 二维已经变成一维了, 1 (a,b) -> a * M + b
|
|
|
|
|
// 设置距离record[a * M +b ] = 1
|
|
|
|
|
public static int infect(int[][] m, int i, int j, int N, int M, int[] curs, int index, int[] record) {
|
|
|
|
|
if (i < 0 || i == N || j < 0 || j == M || m[i][j] != 1) {
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
// m[i][j] 不越界,且m[i][j] == 1
|
|
|
|
|
m[i][j] = 2;
|
|
|
|
|
int p = i * M + j;
|
|
|
|
|
record[p] = 1;
|
|
|
|
|
// 收集到不同的1
|
|
|
|
|
curs[index++] = p;
|
|
|
|
|
index = infect(m, i - 1, j, N, M, curs, index, record);
|
|
|
|
|
index = infect(m, i + 1, j, N, M, curs, index, record);
|
|
|
|
|
index = infect(m, i, j - 1, N, M, curs, index, record);
|
|
|
|
|
index = infect(m, i, j + 1, N, M, curs, index, record);
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 二维原始矩阵中,N总行数,M总列数
|
|
|
|
|
// all 总 all = N * M
|
|
|
|
|
// V 要生成的是第几层 curs V-1 nexts V
|
|
|
|
|
// record里面拿距离
|
|
|
|
|
public static int bfs(int N, int M, int all, int V,
|
|
|
|
|
int[] curs, int size, int[] nexts, int[] record) {
|
|
|
|
|
int nexti = 0; // 我要生成的下一层队列成长到哪了?
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
|
// curs[i] -> 一个位置
|
|
|
|
|
int up = curs[i] < M ? -1 : curs[i] - M;
|
|
|
|
|
int down = curs[i] + M >= all ? -1 : curs[i] + M;
|
|
|
|
|
int left = curs[i] % M == 0 ? -1 : curs[i] - 1;
|
|
|
|
|
int right = curs[i] % M == M - 1 ? -1 : curs[i] + 1;
|
|
|
|
|
if (up != -1 && record[up] == 0) {
|
|
|
|
|
record[up] = V;
|
|
|
|
|
nexts[nexti++] = up;
|
|
|
|
|
}
|
|
|
|
|
if (down != -1 && record[down] == 0) {
|
|
|
|
|
record[down] = V;
|
|
|
|
|
nexts[nexti++] = down;
|
|
|
|
|
}
|
|
|
|
|
if (left != -1 && record[left] == 0) {
|
|
|
|
|
record[left] = V;
|
|
|
|
|
nexts[nexti++] = left;
|
|
|
|
|
}
|
|
|
|
|
if (right != -1 && record[right] == 0) {
|
|
|
|
|
record[right] = V;
|
|
|
|
|
nexts[nexti++] = right;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nexti;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|