Code.Dev_MH
DevMHK
Code.Dev_MH
전체 방문자
오늘
어제
  • 개발자의 일상 (40)
    • Language (5)
      • Java (4)
      • Kotlin (1)
      • Python (0)
    • Back-End (1)
      • Spring (1)
      • Django (0)
      • Error (0)
    • Infra (0)
      • Docker (0)
      • CI, CD (0)
      • AWS (0)
    • CS (12)
      • 컴퓨터 구조(Computer Architectur.. (12)
      • 운영 체제(OS) (0)
      • 시스템소프트웨어(SystemSoftware) (0)
      • 네트워크(Network) (0)
      • 소프트웨어공학(Software Engineerin.. (0)
      • 데이터베이스(DataBase) (0)
      • 자료구조(Data Structure) (0)
      • 알고리즘(Algorithm) (0)
    • Git (0)
    • Algorithm (21)
      • 프로그래머스 (5)
      • 백준 (16)
      • 코딩테스트 후기 (0)
    • 회고 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • INT
  • dp
  • Greedy
  • computer architecture
  • 제로베이스백엔드스쿨
  • 컴퓨터구조
  • 너비우선탐색
  • 다이나믹프로그래밍
  • 우선순위 큐
  • 브루트포스
  • 그리디
  • 프로그래머스
  • BFS
  • 코틀린장점
  • java
  • Priority Queue
  • 자바와비교
  • 코틀린사용이유
  • cs
  • 백준

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Code.Dev_MH

DevMHK

[백준_16234] 인구 이동
Algorithm/백준

[백준_16234] 인구 이동

2023. 1. 17. 12:00

문제

백준 16234번
https://www.acmicpc.net/problem/16234

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모든 나라는 1×1 크기이기 때문에, 모든 국경선은 정사각형 형태이다.

오늘부터 인구 이동이 시작되는 날이다.

인구 이동은 하루 동안 다음과 같이 진행되고, 더 이상 아래 방법에 의해 인구 이동이 없을 때까지 지속된다.

  • 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면, 두 나라가 공유하는 국경선을 오늘 하루 동안 연다.
  • 위의 조건에 의해 열어야하는 국경선이 모두 열렸다면, 인구 이동을 시작한다.
  • 국경선이 열려있어 인접한 칸만을 이용해 이동할 수 있으면, 그 나라를 오늘 하루 동안은 연합이라고 한다.
  • 연합을 이루고 있는 각 칸의 인구수는 (연합의 인구수) / (연합을 이루고 있는 칸의 개수)가 된다. 편의상 소수점은 버린다.
  • 연합을 해체하고, 모든 국경선을 닫는다.

각 나라의 인구수가 주어졌을 때, 인구 이동이 며칠 동안 발생하는지 구하는 프로그램을 작성하시오.

첫째 줄에 N, L, R이 주어진다. (1 ≤ N ≤ 50, 1 ≤ L ≤ R ≤ 100)
둘째 줄부터 N개의 줄에 각 나라의 인구수가 주어진다. r행 c열에 주어지는 정수는 A[r][c]의 값이다. (0 ≤ A[r][c] ≤ 100)

인구 이동이 발생하는 일수가 2,000번 보다 작거나 같은 입력만 주어진다.
인구 이동이 며칠 동안 발생하는지 첫째 줄에 출력한다.

  • 생각해보기

Code

  • 이동할 move 메서드를 만든다.
  • 방문 확인을 위해 isVisited를 만들고 방문을 했다면 continue해준다.
  • 방문을 하지 않았다면 현재 나라에서 bfs를 통해 주변 나라의 인구를 한다.
  • bfs에 queue를 통해 현재 나라의 좌표를 넣고 상, 하, 좌, 우의 나라를 확인한다.
  • 그 중 범위를 벗어난 위치에 대해서는 continue를 통해 넘어간다.
  • 범위 안에 있는 나라에 대해서는 L(최소)< 인구 수의 차이 < R(최대) 를 통해 이동한 나라에 대해 queue에 넣어주고 isVisited에 방문 확인으로 true를 만들어준다.
  • 또한, 이동할 인구에 대해서 sum을 하고 list를 통해 인구가 이동해야 할 나라에 대해 넣어준다.
  • 상, 하, 좌, 우 다 끝나면 bfs를 종료하고 이동할 나라에 대해 인구 수의 합(sum)과 list(인구가 이동해야 할 나라들의 좌표)의 size를 통해 평균을 구한다.
  • 이동해야할 나라에 대해서는 평균값으로 대체한다.
  • 그리고 isMove를 통해 이동했음을 표시한다.
  • 위 순서를 반복하면서 더 이상 인구 수의 차이가 최소인 L과 최대인 R 사이의 존재하지 않는다면 총 이동한 횟수에 대해 반환한다.

Java

import java.io.*;
import java.util.*;

class Node {
    int x;
    int y;

    public Node(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Main {
    static int N, L, R;
    static int[][] board;
    static boolean[][] isVisited; // 방문 확인
    static int[] dx = {0, 1, 0, -1}; // x축 이동
    static int[] dy = {1, 0, -1, 0}; // y축 이동
    static ArrayList<Node> list; // 인구 이동이 필요한 좌표의 리스트
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        L = Integer.parseInt(st.nextToken()); // 최소 인구 차이
        R = Integer.parseInt(st.nextToken()); // 최대 인구 차이
        board = new int[N][N]; // 땅의 크기에 따른 인구 수

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        System.out.println(move());
    }

    public static int move() { // 인구 이동
        int result = 0;

        while (true) {
            boolean isMove = false;
            isVisited = new boolean[N][N];

            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (isVisited[i][j]) { // 이전의 방문 했을 경우
                        continue;
                    }
                    // 현재 나라에서 주변 나라를 확인하며 이동할 인구 수의 총합 
                    int sum = bfs(i, j);

                    if (list.size() > 1) {
                        // 인구 변경
                        int avg = sum / list.size();
                        for (Node node : list) {
                            board[node.x][node.y] = avg;
                        }
                        isMove = true;
                    }
                }
            }

            if (!isMove) { // 더 이상 이동이 없을 경우
                return result;
            }
            result++;
        }
    }

    public static int bfs(int i, int j) {
        Queue<Node> queue = new LinkedList<>();
        list = new ArrayList<>();

        queue.offer(new Node(i, j));
        list.add(new Node(i, j));
        isVisited[i][j] = true;

        int sum = board[i][j];
        while (!queue.isEmpty()) {
            Node cur = queue.poll();

            for (int k = 0; k < dx.length; k++) {
                // 주변 나라로 이동
                int x = cur.x + dx[k];
                int y = cur.y + dy[k];

                // 범위에서 벗어났을 경우
                if (x < 0 || y < 0 || x >= N || y >= N || isVisited[x][y]) {
                    continue;
                }
                // 주변 나라와의 인구 수의 차이
                int diff = Math.abs(board[cur.x][cur.y] - board[x][y]);
                // 지정한 최소 및 최대 인구 수 사이에 있는 경우
                if (L <= diff && diff <= R) {
                    queue.offer(new Node(x, y));
                    list.add(new Node(x, y));
                    sum += board[x][y];
                    isVisited[x][y] = true;
                }
            }
        }
        return sum;
    }
}
반응형

'Algorithm > 백준' 카테고리의 다른 글

[백준_12865] 평범한 배낭  (0) 2023.01.30
[백준_14725] 개미굴  (0) 2023.01.19
[백준_16401] 과자 나눠주기  (1) 2023.01.15
[백준_1041] 주사위  (0) 2023.01.12
[백준_14235] 크리스마스 선물  (0) 2023.01.08
    'Algorithm/백준' 카테고리의 다른 글
    • [백준_12865] 평범한 배낭
    • [백준_14725] 개미굴
    • [백준_16401] 과자 나눠주기
    • [백준_1041] 주사위
    Code.Dev_MH
    Code.Dev_MH
    Back-End 개발자가 되기 위한 개발 노트(Java)

    티스토리툴바