[BOJ] 2146. 다리 만들기
- 메모리 : 18,056 KB
- 시간 : 184 ms
- 코드길이 : 3,056 B
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N, islandIdx, result;
static int[][] map;
static boolean[][] visited;
static int[][] delta = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // 상 우 하 좌
static ArrayList<Point> points;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
map = new int[N][N];
visited = new boolean[N][N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
} // end input
// 섬끼리 숫자 라벨링 해주기 (BFS)
islandIdx = 2;
points = new ArrayList<Point>();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 1) {
findIsland(i, j);
islandIdx++;
}
}
}
// 섬끼리 연결하는 다리 찾기 (BFS)
result = Integer.MAX_VALUE;
for (Point p : points) {
makeBridge(p);
}
System.out.println(result);
in.close();
}// end main
// BFS
private static void makeBridge(Point p) {
Queue<Point> queue = new LinkedList<Point>();
queue.offer(p);
for (boolean[] row : visited) {
Arrays.fill(row, false);
}
visited[p.i][p.j] = true;
while (!queue.isEmpty()) {
Point cur = queue.poll();
if (cur.d >= result) {
break;
}
for (int n = 0; n < delta.length; n++) {
int curX = cur.i + delta[n][0];
int curY = cur.j + delta[n][1];
if (isIn(curX, curY) && !visited[curX][curY]) {
visited[curX][curY] = true;
if (map[curX][curY] == cur.idx)
continue;
else if (map[curX][curY] == 0)
queue.offer(new Point(curX, curY, cur.d + 1, cur.idx));
else if (map[curX][curY] != cur.idx) {
result = Math.min(result, cur.d);
return;
}
}
}
}
}
// BFS
private static void findIsland(int i, int j) {
Queue<Point> queue = new LinkedList<Point>();
queue.offer(new Point(i, j, 0, islandIdx));
points.add(new Point(i, j, 0, islandIdx));
map[i][j] = islandIdx;
while (!queue.isEmpty()) {
Point cur = queue.poll();
for (int n = 0; n < delta.length; n++) {
int curX = cur.i + delta[n][0];
int curY = cur.j + delta[n][1];
if (isIn(curX, curY) && map[curX][curY] == 1) {
map[curX][curY] = islandIdx;
queue.offer(new Point(curX, curY, 0, islandIdx));
points.add(new Point(curX, curY, 0, islandIdx));
}
}
}
}
private static boolean isIn(int curX, int curY) {
return curX >= 0 && curX < N && curY >= 0 && curY < N;
}
static class Point {
int i;
int j;
int d;
int idx;
public Point(int i, int j, int d, int idx) {
super();
this.i = i;
this.j = j;
this.d = d;
this.idx = idx;
}
}
}
- 메모리 : 137,872 KB
- 시간 : 272 ms
- 코드길이 : 2965 B
- 위와 같은 코드이지만 visited 배열을 전역 변수로 선언하고 메소드 호출이 될 경우마다 생성하는 아래 코드와 Arrays.fill()을 이용하여 초기화 시켜주는 위의 코드를 비교하면 Arrays.fill()을 사용하는 것이 메모리와 시간 면에서 훨씬 효율적임을 확인할 수 있다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N, islandIdx, result;
static int[][] map;
static boolean[][] visited;
static int[][] delta = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // 상 우 하 좌
static ArrayList<Point> points;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
map = new int[N][N];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
} // end input
// 섬끼리 숫자 라벨링 해주기 (BFS)
islandIdx = 2;
points = new ArrayList<Point>();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 1) {
findIsland(i, j);
islandIdx++;
}
}
}
// 섬끼리 연결하는 다리 찾기 (BFS)
result = Integer.MAX_VALUE;
for (Point p : points) {
makeBridge(p);
}
System.out.println(result);
in.close();
}// end main
// BFS
private static void makeBridge(Point p) {
visited = new boolean[N][N];
Queue<Point> queue = new LinkedList<Point>();
queue.offer(p);
visited[p.i][p.j] = true;
while (!queue.isEmpty()) {
Point cur = queue.poll();
if (cur.d >= result) {
break;
}
for (int n = 0; n < delta.length; n++) {
int curX = cur.i + delta[n][0];
int curY = cur.j + delta[n][1];
if (isIn(curX, curY) && !visited[curX][curY]) {
visited[curX][curY] = true;
if (map[curX][curY] == cur.idx)
continue;
else if (map[curX][curY] == 0)
queue.offer(new Point(curX, curY, cur.d + 1, cur.idx));
else if (map[curX][curY] != cur.idx) {
result = Math.min(result, cur.d);
return;
}
}
}
}
}
// BFS
private static void findIsland(int i, int j) {
Queue<Point> queue = new LinkedList<Point>();
queue.offer(new Point(i, j, 0, islandIdx));
points.add(new Point(i, j, 0, islandIdx));
map[i][j] = islandIdx;
while (!queue.isEmpty()) {
Point cur = queue.poll();
for (int n = 0; n < delta.length; n++) {
int curX = cur.i + delta[n][0];
int curY = cur.j + delta[n][1];
if (isIn(curX, curY) && map[curX][curY] == 1) {
map[curX][curY] = islandIdx;
queue.offer(new Point(curX, curY, 0, islandIdx));
points.add(new Point(curX, curY, 0, islandIdx));
}
}
}
}
private static boolean isIn(int curX, int curY) {
return curX >= 0 && curX < N && curY >= 0 && curY < N;
}
static class Point {
int i;
int j;
int d;
int idx;
public Point(int i, int j, int d, int idx) {
super();
this.i = i;
this.j = j;
this.d = d;
this.idx = idx;
}
}
}
Leave a comment