알고리즘/BOJ

BJ G3 2146 다리만들기

  • -
반응형

BJ G3 2146 다리만들기

 

 

문제링크

https://www.acmicpc.net/problem/2146

 

2146번: 다리 만들기

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

www.acmicpc.net

* 일단 문제를 정독 하고 1시간 이상 반드시 고민이 필요합니다.

 

동영상 설명

1시간 이상 고민 했지만 아이디어가 떠오르지 않는다면 동영상에서 약간의 힌트를 얻어봅시다.

 

소스 보기

동영상 설명을 보고도 전혀 구현이 안된다면 이건 연습 부족입니다.
소스를 보고 작성해 본 후 스스로 백지 상태에서 3번 작성해 볼 의지가 있다면 소스를 살짝 보세요.

더보기
package bj.gold.l4;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;


public class BJ_G4_2146_다리만들기 {
    static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    static int N, A, islandIdx;
    static int[][] map;
    static boolean[][] visited;
    static List<Point> points;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br = new BufferedReader(new StringReader(src));

        N = Integer.parseInt(br.readLine());// N(100이하의 자연수)
        map = new int[N][N];
        visited = new boolean[N][N];
        StringTokenizer tokens = null;
        for (int r = 0; r < N; r++) {
            tokens = new StringTokenizer(br.readLine());
            for (int c = 0; c < N; c++) {
                map[r][c] = Integer.parseInt(tokens.nextToken());
            }
        }

        points = new LinkedList<>();
        islandIdx = 2;
        for (int r = 0; r < N; r++) {
            for (int c = 0; c < N; c++) {
                if (map[r][c] == 1) {
                    bfsMarkIslandNum(r, c);
                    islandIdx++;
                }
            }
        }

        /*
        System.out.println("섬 정보 확인");
        for (int[] row : map) {
            System.out.println(Arrays.toString(row));
        }*/

        // 각 섬에서 다른 섬까지 최단 거리 찾아보기.
        A = Integer.MAX_VALUE;
        for (Point p : points) {
            bfsGetShortBridgeLength(p);
        }
        System.out.println(A);
    }

    static void bfsGetShortBridgeLength(Point p) {
        Queue<Point> q = new LinkedList<>();
        q.offer(p);
        for (boolean[] row : visited) {
            Arrays.fill(row, false);
        }

        while (!q.isEmpty()) {
            Point front = q.poll();
            if (front.d >= A) {
                System.out.println("불필요");
                break;
            }
            for (int d = 0; d < dirs.length; d++) {
                int nr = front.r + dirs[d][0];
                int nc = front.c + dirs[d][1];

                // 범위 안에 있고 미방문 지점이면 가보자.
                if (isIn(nr, nc) && !visited[nr][nc]) {
                    visited[nr][nc] = true;
                    // 내륙으로 들어가는 것은 관심 없다.
                    if (map[nr][nc] == front.id) {
                        continue;
                    }
                    // 그 지점이 0이면 다리 놓기로 전진한다.
                    else if (map[nr][nc] == 0) {
                        q.offer(new Point(nr, nc, front.d + 1, front.id));
                    }
                    // 현재 지점과 다른 값이면 거기가 신대륙!! 거리 계산
                    else if (map[nr][nc] != front.id) {
                        A = Math.min(A, front.d);
                        return;
                    }
                }
            }
        }
    }

    static void bfsMarkIslandNum(int r, int c) {
        Queue<Point> q = new LinkedList<>();
        Point p = new Point(r, c, 0, islandIdx);
        q.offer(p);
        map[r][c] = islandIdx;

        points.add(p);

        while (!q.isEmpty()) {
            Point front = q.poll();

            for (int d = 0; d < dirs.length; d++) {
                int nr = front.r + dirs[d][0];
                int nc = front.c + dirs[d][1];

                if (isIn(nr, nc)) {
                    if (map[nr][nc] == 1) {
                        map[nr][nc] = islandIdx;
                        p = new Point(nr, nc, 0, islandIdx);
                        q.offer(p);
                        points.add(p);
                    }
                }
            }
        }
    }

    static boolean isIn(int r, int c) {
        return 0 <= r && r < N && 0 <= c && c < N;
    }

    static class Point {
        int r, c, d, id;

        public Point(int r, int c, int d, int id) {
            this.r = r;
            this.c = c;
            this.d = d;
            this.id = id;
        }

        @Override
        public String toString() {
            return "[" + r + "," + c + "," + d + "]";
        }


    }

    private static String src = "10\r\n" +
                                "1 1 1 0 0 0 0 1 1 1\r\n" +
                                "1 1 1 1 0 0 0 0 1 1\r\n" +
                                "1 0 1 1 0 0 0 0 1 1\r\n" +
                                "0 0 1 1 1 0 0 0 0 1\r\n" +
                                "0 0 0 1 0 0 0 0 0 1\r\n" +
                                "0 0 0 0 0 0 0 0 0 1\r\n" +
                                "0 0 0 0 0 0 0 0 0 0\r\n" +
                                "0 0 0 0 1 1 0 0 0 0\r\n" +
                                "0 0 0 0 1 1 1 0 0 0\r\n" +
                                "0 0 0 0 0 0 0 0 0 0";
}

 

반응형

'알고리즘 > BOJ' 카테고리의 다른 글

BJ G1 13976 타일채우기 2  (0) 2020.05.02
BJ S2 2133 타일채우기  (0) 2020.05.02
BJ S3 6987 월드컵  (0) 2020.04.29
BJ G3 17472 다리 만들기 2  (0) 2020.04.27
BJ G5 15686 치킨배달  (0) 2020.04.26
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.