[백준 16234. 인구 이동]

youngtae·2023년 4월 2일
0

알고리즘 문제 풀이

목록 보기
10/12
post-thumbnail

문제

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

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

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

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

풀이

우선 BFS로 이동가능한 연합국을 모두 찾은뒤 계산한 값으로 변경해야한다.

주의할 점은 인구이동이 없을 때까지 지속되므로 while문 안에서 계속 완전탐색을 돌려주어야 한다.

함수의 내용은 이동 가능한 나라를 찾으면 연합국 리스트에 추가해놓고 BFS가 끝났을 때 처음위치 제외 연합국이 존재한다면 인구이동시작으로 구성했다.

# memory: 34216KB  time: 4620ms (python)

from collections import deque
import sys
input = sys.stdin.readline


def BFS(r, c):
    q.append([r, c])
    union = [[r, c]]
    # 연합국 인구 수
    sm = arr[r][c]
    v[r][c] = 1
    while q:
        ci, cj = q.popleft()
        for di, dj in move:
            ni, nj = ci + di, cj + dj
            # 범위 안이고 방문안했으면
            if 0 <= ni < N and 0 <= nj < N and v[ni][nj] == 0:
                # 이동가능하면 엽합국에 추가
                if L <= abs(arr[ni][nj] - arr[ci][cj]) <= R:
                    v[ni][nj] = 1
                    union.append([ni, nj])
                    sm += arr[ni][nj]
                    q.append([ni, nj])

    if len(union) > 1:
        # 인구이동 시작
        for x, y in union:
            arr[x][y] = sm // len(union)

    return sm


N, L, R = map(int, input().split())
arr = [list(map(int, input().split())) for _ in range(N)]
q = deque()
# 연합국 좌표
union = []
# 인구이동 횟수
cnt = 0

move = ((-1, 0), (1, 0), (0, -1), (0, 1))
flag = True
# 인구이동 없을때까지 지속
while flag:
    v = [[0] * N for _ in range(N)]
    flag = False
    for i in range(N):
        for j in range(N):
            if v[i][j] == 0:
                # 연합국이 2개 이상이면
                sm = BFS(i, j)
                if sm > arr[i][j]:
                    flag = True

    if not flag:
        break
    cnt += 1

print(cnt)
profile
나의 개발기록

0개의 댓글