Algorithm
백준_다리만들기_2146
Young_J
2020. 9. 16. 01:42
알고리즘
섬과 섬을 연결할 수 있는 다리의 길이가 최소인값을 찾는 알고리즘
1. dfs탐색을 통해 섬의 정보를 알아야 함. 각각 넘버링
예) 섬이 3개라면 -> 1번섬, 2번섬, 3번섬
2. 섬의 가장자리 즉, 바다와(0) 근접해있는 곳은 bfs탐색을 시작함
- 탐색 기준은 자신의 넘버와 같지않은곳을 따라가면서 탐색(count + 1)
- 해당지점의 넘버링값을 보고 자신의 넘버링값과 다르다면 최소값을 갱신하고 리턴. 단, 현재의 cnt값에서 -1해줘야 함.
- 모든섬이 연결되어 bfs를 돌릴 수 없는 경우도 있을 수 있기 때문에 Ans가 Max값이라면 0 출력! 아니면 Ans값 출력
* bfs를 사용한 이유 : 최소값을 찾는 알고리즘이기 때문
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class 다리만들기_2146 {
static int N, map[][], Ans = Integer.MAX_VALUE;
static boolean[][] v;
static int[] dr = { -1, 1, 0, 0 };
static int[] dc = { 0, 0, -1, 1 };
static Queue<Point> q = new LinkedList<Point>();
static class Point {
int r, c, cnt, num;
public Point(int r, int c, int cnt, int number) {
super();
this.r = r;
this.c = c;
this.cnt = cnt;
this.num = number;
}
public Point(int r, int c, int cnt) {
super();
this.r = r;
this.c = c;
this.cnt = cnt;
}
@Override
public String toString() {// 디버깅을 위해
return "Point [r=" + r + ", c=" + c + ", cnt=" + cnt + "]";
}
}
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
map = new int[N][N];
v = new boolean[N][N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
int cnt = 1;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map.length; j++) {
if (map[i][j] == 1 && !v[i][j]) {
dfs(new Point(i, j, cnt));
cnt++;
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if(map[i][j] == 0) continue;
for (int k = 0; k < 4; k++) {
int nr = i + dr[k];
int nc = j + dc[k];
if (nr < 0 || nc < 0 || nr >= N || nc >= N)
continue;
if (map[nr][nc] == 0) {
bfs(new Point(i, j, 0, map[i][j]), new boolean[N][N]);
q.clear();
break;
}
}
}
}
// bfs(new Point(0, 2, 0, map[0][2]), new boolean[N][N]);
System.out.println(Ans == Integer.MAX_VALUE ? 0 : Ans);
// print(map);
}
private static void bfs(Point point, boolean[][] v) {
v[point.r][point.c] = true;
q.add(point);
while (!q.isEmpty()) {
Point p = q.poll();
if (map[p.r][p.c] != p.num && map[p.r][p.c] != 0) {
Ans = Math.min(Ans, p.cnt - 1);
return;
}
for (int k = 0; k < 4; k++) {
int nr = p.r + dr[k];
int nc = p.c + dc[k];
if (nr < 0 || nc < 0 || nr >= N || nc >= N || map[nr][nc] == p.num)
continue;
if (!v[nr][nc]) {
v[nr][nc] = true;
q.add(new Point(nr, nc, p.cnt + 1, p.num));
}
}
}
}
private static void dfs(Point point) {
Point p = point;
v[p.r][p.c] = true;
map[p.r][p.c] = p.cnt;
for (int k = 0; k < 4; k++) {
int nr = p.r + dr[k];
int nc = p.c + dc[k];
if (nr < 0 || nc < 0 || nr >= N || nc >= N)
continue;
if (map[nr][nc] == 1 && !v[nr][nc])
dfs(new Point(nr, nc, p.cnt));
}
}
private static void print(int[][] map) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}