티스토리 뷰

Algorithm/Solution

[백준 2146] - 다리 만들기

기내식은수박바 2020. 3. 7. 13:17
반응형

문제

  • 여러 섬으로 이루어진 나라가 있다.
  • 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다.
    • 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다는 생각을 하게 되었다.
    • 그래서 그는, 생색내는 식으로 한 섬과 다른 섬을 잇는 다리 하나만을 만들기로 하였고, 그 또한 다리를 가장 짧게 하여 돈을 아끼려 하였다.
  • 이 나라는 N × N 크기의 이차원 평면상에 존재한다.
    • 이 나라는 여러 섬으로 이루어져 있으며, 섬이란 동서남북으로 육지가 붙어있는 덩어리를 말한다.
    • 다음은 세 개의 섬으로 이루어진 나라의 지도이다.

  • 위의 그림에서 색이 있는 부분이 육지이고, 색이 없는 부분이 바다이다.
    • 이 바다에 가장 짧은 다리를 놓아 두 대륙을 연결하고자 한다.
    • 가장 짧은 다리란, 다리가 격자에서 차지하는 칸의 수가 가장 작은 다리를 말한다.
    • 다음 그림에서 두 대륙을 연결하는 다리를 볼 수 있다.

  • 물론 위의 방법 외에도 다리를 놓는 방법이 여러 가지 있으나, 위의 경우가 놓는 다리의 길이가 3으로 가장 짧다 (물론 길이가 3인 다른 다리를 놓을 수 있는 방법도 몇 가지 있다).
  • 지도가 주어질 때, 가장 짧은 다리 하나를 놓아 두 대륙을 연결하는 방법을 찾으시오.

 

입력

  • 첫 줄에는 지도의 크기 N(100이하의 자연수)가 주어진다.
    • 그 다음 N줄에는 N개의 숫자가 빈칸을 사이에 두고 주어지며, 0은 바다, 1은 육지를 나타낸다.
  • 항상 두 개 이상의 섬이 있는 데이터만 입력으로 주어진다.

 

출력

  • 첫째 줄에 가장 짧은 다리의 길이를 출력한다.

 

 

솔루션

  • 먼저 BFS를 수행하여 대륙마다 각각 다른 번호를 지정해준다.
    • 예를 들면, 첫 번째 대륙은 2, 두 번째 대륙은 3
    • 대륙에 번호를 지정함과 동시에 대륙의 좌표 정보를 모은다.
  • 대륙에 번호를 지정하고 난 다음, 다리 건설을 시작한다.
    • 위에서 모은 대륙 좌표 정보를 모두 큐에 집어넣고 현재 큐 크기를 변수에 담아 이 값만큼 반복을 수행한다.
      • 좌표에서 부터 BFS를 수행한다.
        • 바다 (좌표 값이 0) 를 만났을 경우, 방문 여부를 확인한다.
          • 현재 바다를 방문한 적이 있다면, 다른 좌표로 넘어가 다시 BFS를 수행한다.
          • 현재 바다를 방문한 적이 없다면, 방문 표시를 하고 큐에 해당 바다 좌표 정보를 삽입한다.
        • 대륙을 만났을 경우, 대륙 번호를 확인한다.
          • 대륙 번호가 같다면, 동일한 대륙이므로 다시 BFS를 수행한다.
          • 대륙 번호가 같지 않다면, 다른 대륙에 도착한 것이므로 현재 다리길이 값을 반환한다.
      • 반복문을 수행하고 나오면 아직 대륙을 찾지 못한 것이므로, 다리길이를 1 증가시키고 다시 처음부터 수행한다.
  • 핵심은 다리 건설을 시작할 때 큐에 정보들을 집어넣고 현재 큐 크기만큼 반복문을 수행하는 것이 아니라 처음 큐 크기를 따로 담은 뒤 정해진 그 크기만큼 수행한다는 것이다.
    • 이 반복문 없이 그냥 수행한다면 한쪽방향으로 계속 진행하는 경우가 있을 수 있고, 결국 대륙에 도달했지만 이 최소 값이 아닌 값을 가지고 다리 건설 과정이 종료된다.
  • 그림을 통해 보자.
    • 처음 대륙에 숫자 지정 작업을 끝내고, 다리를 건설한다고 해보자.
      • 그러면 큐에는 아래 빨간색 점들의 정보가 들어가 있을 것이다.

  • 여기서 다리를 건설하기 위해 개수만큼 BFS를 수행한다.
    • 그러면 큐에는 위 정보들이 빠져나올거고 아래와 같은 좌표 정보들이 담길 것이다.

  • 마찬가지로 위와 동일하게 현재 담긴 큐 크기 (위 빨간색 좌표) 만큼 다리 건설을 수행하면 아래와 같은 정보들로 바뀐다.

  • 위와 같은 수행을 다른 대륙을 만날 때까지 진행하면 최종적으로 현재 대륙에서 다른 대륙으로 가기 위해 필요한 최소 다리길이를 얻을 수 있다.
    • 반복문이 없다면 동일하게 한 칸씩 진행되는 것이 아닌 어느 부분에서는 그 진행방향이 최소 다리길이를 구하는 곳이 아니더라도 두 칸, 세 칸 먼저 진행되어 대륙에 먼저 도달할 수도 있다. 
  • 이 작업들을 현재 대륙 뿐만 아니라 다른 대륙에 대해서도 동일하게 수행하여 최소 다리길이를 얻은 다음, 이전에 얻었던 최소 다리길이와 비교하여 값을 갱신하거나 기존 값을 유지하는 것이다.

 

Code

대륙 번호 매기기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static void NumberingContinent(int x, int y, int num, LinkedList<Point> conti) {
    Queue<Point> queue = new LinkedList<>();
 
    visited[x][y] = true;
    map[x][y] = num;
    queue.offer(new Point(x, y));
    conti.add(new Point(x, y));
 
    while (!queue.isEmpty()) {
        Point cur = queue.poll();
 
        for (int i = 0; i < 4; i++) {
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];
 
            if (0 <= nx && nx < N && 0 <= ny && ny < N) {
                if (!visited[nx][ny] && map[nx][ny] == 1) {
                    queue.offer(new Point(nx, ny));
                    visited[nx][ny] = true;
                    map[nx][ny] = num;
                    conti.add(new Point(nx, ny));
                }
            }
        }
    }
}
 
cs

 

다리 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static int ConstructingBridge(LinkedList<Point> conti, int num) {
    int bridge = 0;
    Queue<Point> queue = new LinkedList<>();
 
    queue.addAll(conti);
 
    while (!queue.isEmpty()) {
        int continum = queue.size();
 
        for (int k = 0; k < continum; k++) {
            Point cur = queue.poll();
 
            for (int i = 0; i < 4; i++) {
                int nx = cur.x + dx[i];
                int ny = cur.y + dy[i];
 
                if (0 <= nx && nx < N && 0 <= ny && ny < N) {
                    if(map[nx][ny] == 0) {
                        if(!visited[nx][ny]) {
                            queue.offer(new Point(nx, ny));
                            visited[nx][ny] = true;
                        }
                    } else if(map[nx][ny] != num)
                        return bridge;
                }
            }
        }
 
        bridge++;
    }
 
    return bridge;
}
cs

 

결과

반응형

'Algorithm > Solution' 카테고리의 다른 글

[백준 1261] - 알고스팟  (0) 2020.03.09
[백준 3055] - 탈출  (0) 2020.03.08
[백준 1475] - 방 번호  (0) 2020.03.05
[백준 2504] - 괄호의 값  (2) 2020.03.04
[프로그래머스] - 쇠막대기  (0) 2020.03.04
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함