You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.0 KiB
123 lines
3.0 KiB
package class_2021_12_2_week;
|
|
|
|
// 来自美团
|
|
// 所有黑洞的中心点记录在holes数组里
|
|
// 比如[[3,5] [6,9]]表示,第一个黑洞在(3,5),第二个黑洞在(6,9)
|
|
// 并且所有黑洞的中心点都在左下角(0,0),右上角(x,y)的区域里
|
|
// 飞船一旦开始进入黑洞,就会被吸进黑洞里
|
|
// 返回:
|
|
// 如果统一所有黑洞的半径,最大半径是多少,依然能保证飞船从(0,0)能到达(x,y)
|
|
// 1000 1000*1000 10^6 * 二分
|
|
public class Code02_AwayFromBlackHole {
|
|
|
|
public static int maxRadius(int[][] holes, int x, int y) {
|
|
int L = 1;
|
|
int R = Math.max(x, y);
|
|
int ans = 0;
|
|
while (L <= R) {
|
|
int M = (L + R) / 2;
|
|
if (ok(holes, M, x, y)) {
|
|
ans = M;
|
|
L = M + 1;
|
|
} else {
|
|
R = M - 1;
|
|
}
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
public static boolean ok(int[][] holes, int r, int x, int y) {
|
|
int n = holes.length;
|
|
UnionFind uf = new UnionFind(holes, n, r);
|
|
for (int i = 0; i < n; i++) {
|
|
for (int j = i; j < n; j++) {
|
|
if (touch(holes[i][0], holes[i][1], holes[j][0], holes[j][1], r)) {
|
|
uf.union(i, j);
|
|
}
|
|
if (uf.block(i, x, y)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static boolean touch(int x1, int y1, int x2, int y2, int r) {
|
|
return (r << 1) >= Math.sqrt((Math.pow(Math.abs(x1 - x2), 2) + Math.pow(Math.abs(y1 - y2), 2)));
|
|
}
|
|
|
|
public static class UnionFind {
|
|
public int[] father;
|
|
public int[] size;
|
|
public int[] xmin;
|
|
public int[] xmax;
|
|
public int[] ymin;
|
|
public int[] ymax;
|
|
public int[] help;
|
|
|
|
public UnionFind(int[][] holes, int n, int r) {
|
|
father = new int[n];
|
|
size = new int[n];
|
|
xmin = new int[n];
|
|
xmax = new int[n];
|
|
ymin = new int[n];
|
|
ymax = new int[n];
|
|
help = new int[n];
|
|
for (int i = 0; i < n; i++) {
|
|
father[i] = i;
|
|
size[i] = 1;
|
|
xmin[i] = holes[i][0] - r;
|
|
xmax[i] = holes[i][0] + r;
|
|
ymin[i] = holes[i][1] - r;
|
|
ymax[i] = holes[i][1] + r;
|
|
}
|
|
}
|
|
|
|
private int find(int i) {
|
|
int hi = 0;
|
|
while (i != father[i]) {
|
|
help[hi++] = i;
|
|
i = father[i];
|
|
}
|
|
for (hi--; hi >= 0; hi--) {
|
|
father[help[hi]] = i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public void union(int i, int j) {
|
|
int fatheri = find(i);
|
|
int fatherj = find(j);
|
|
if (fatheri != fatherj) {
|
|
int sizei = size[fatheri];
|
|
int sizej = size[fatherj];
|
|
int big = sizei >= sizej ? fatheri : fatherj;
|
|
int small = big == fatheri ? fatherj : fatheri;
|
|
father[small] = big;
|
|
size[big] = sizei + sizej;
|
|
xmin[big] = Math.min(xmin[big], xmin[small]);
|
|
xmax[big] = Math.max(xmax[big], xmax[small]);
|
|
ymin[big] = Math.min(ymin[big], ymin[small]);
|
|
ymax[big] = Math.max(ymax[big], ymax[small]);
|
|
}
|
|
}
|
|
|
|
public boolean block(int i, int x, int y) {
|
|
i = find(i);
|
|
return (xmin[i] <= 0 && xmax[i] >= x)
|
|
|| (ymin[i] <= 0 && ymax[i] >= y)
|
|
|| (xmin[i] <= 0 && ymin[i] <= 0)
|
|
|| (xmax[i] >= x && ymax[i] >= y);
|
|
}
|
|
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
int[][] holes = { { 1, 2 }, { 4, 4 }, { 3, 0 }, { 5, 2 } };
|
|
int x = 4;
|
|
int y = 6;
|
|
System.out.println(maxRadius(holes, x, y));
|
|
}
|
|
|
|
}
|