728x90
문제 설명
N×N 크기의 땅이 있다. 각 땅에는 나라가 하나씩 존재하며, 각 나라에는 인구수가 있다. 인접한 나라 사이에는 국경선이 있고, 인구 이동은 다음과 같은 과정으로 진행된다:
- 국경선 열기: 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면 국경선을 연다.
- 인구 이동: 국경선이 열려서 연결된 나라들은 연합을 이루고, 연합 내의 인구는 (연합의 총 인구수) / (연합을 이루는 칸의 개수)로 동일하게 분배된다. 소수점은 버린다.
- 국경선 닫기: 모든 국경선을 닫는다.
이 과정이 더 이상 인구 이동이 없을 때까지 반복된다. 인구 이동이 발생하는 일수를 구하는 것이 문제의 목표다.
문제 접근
이 문제는 BFS(너비 우선 탐색)를 활용한 시뮬레이션 문제다. 각 단계별로 인구 이동이 가능한지 확인하고, 가능한 경우 인구를 이동시켜야 한다.
핵심 아이디어
- 시뮬레이션 반복: 인구 이동이 발생하지 않을 때까지 하루씩 시뮬레이션을 반복한다.
- BFS를 통한 연합 찾기: 각 나라를 방문하면서 인접한 나라와의 인구 차이가 조건에 맞는 경우 연합을 형성한다.
- 인구 이동 처리: 형성된 연합에 대해 인구를 재분배한다.
- 인구 이동 여부 확인: 하루 동안 인구 이동이 발생했는지 여부를 확인하여 시뮬레이션 종료 조건을 판단한다.
코드 구현
1. 입력 및 초기화
import sys
from collections import deque
input = sys.stdin.readline
N, L, R = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
- N: 땅의 크기 (N x N)
- L, R: 인구 차이의 최소값과 최대값
- A: 각 나라의 인구 수를 저장하는 2차원 배열
2. 방향 설정
dx = [-1, 1, 0, 0] # 상하좌우 이동을 위한 x 좌표 변화량
dy = [0, 0, -1, 1] # 상하좌우 이동을 위한 y 좌표 변화량
- BFS 탐색 시 상하좌우로 이동하기 위한 방향 설정이다.
3. BFS 함수 구현
def bfs(x, y, visited):
queue = deque()
queue.append((x, y))
union = [(x, y)]
visited[x][y] = True
total_population = A[x][y]
while queue:
x, y = queue.popleft()
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < N and 0 <= ny < N and not visited[nx][ny]:
population_diff = abs(A[x][y] - A[nx][ny])
if L <= population_diff <= R:
visited[nx][ny] = True
queue.append((nx, ny))
union.append((nx, ny))
total_population += A[nx][ny]
return union, total_population
- bfs 함수는 (x, y) 좌표에서 시작하여 연합을 찾는다.
- visited 배열을 이용하여 이미 방문한 나라를 체크한다.
- union 리스트에 연합에 속한 나라의 좌표를 저장한다.
- total_population은 연합의 총 인구수를 저장한다.
- BFS 탐색을 통해 인접한 나라를 확인하고, 인구 차이가 조건에 맞으면 연합에 추가한다.
4. 시뮬레이션 반복
days = 0
while True:
visited = [[False]*N for _ in range(N)]
is_moved = False # 인구 이동 발생 여부
for i in range(N):
for j in range(N):
if not visited[i][j]:
union, total_population = bfs(i, j, visited)
if len(union) > 1:
is_moved = True
new_population = total_population // len(union)
for x, y in union:
A[x][y] = new_population
if not is_moved:
break
days += 1
- days: 인구 이동이 발생한 일수를 저장한다.
- 무한 루프를 통해 인구 이동이 발생하지 않을 때까지 시뮬레이션을 반복한다.
- is_moved 변수를 통해 인구 이동이 발생했는지 여부를 체크한다.
- 각 나라를 방문하면서 BFS를 통해 연합을 찾고, 연합의 인구를 재분배한다.
- 인구 이동이 발생하지 않으면 루프를 탈출한다.
16324 인구이동 정답 코드(Python)
import sys
from collections import deque
input = sys.stdin.readline
N, L, R = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
dx = [-1, 1, 0, 0] # 상하좌우
dy = [0, 0, -1, 1]
def bfs(x, y, visited):
queue = deque()
queue.append((x, y))
union = [(x, y)]
visited[x][y] = True
total_population = A[x][y]
while queue:
x, y = queue.popleft()
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < N and 0 <= ny < N and not visited[nx][ny]:
if L <= abs(A[x][y] - A[nx][ny]) <= R:
visited[nx][ny] = True
queue.append((nx, ny))
union.append((nx, ny))
total_population += A[nx][ny]
return union, total_population
days = 0
while True:
visited = [[False]*N for _ in range(N)]
is_moved = False
for i in range(N):
for j in range(N):
if not visited[i][j]:
union, total_population = bfs(i, j, visited)
if len(union) > 1:
is_moved = True
new_population = total_population // len(union)
for x, y in union:
A[x][y] = new_population
if not is_moved:
break
days += 1
print(days)
16324 인구이동 결과
도움이 되셨다면 공감과 댓글 부탁드립니다.
728x90
'Python > 백준' 카테고리의 다른 글
백준 아기 상어 [16326] 파이썬(Python) 코드 + 해설 (1) | 2024.11.02 |
---|---|
백준 나무 재테크 [16325] 파이썬(Python) 코드 + 해설 (2) | 2024.11.02 |
백준 큐빙 [5373] 파이썬(Python) 코드 + 해설 (0) | 2024.11.01 |
백준 치킨 배달 [15686] 파이썬(Python) 코드 + 해설 (1) | 2024.10.31 |
백준 드래곤 커브 [15685] 파이썬(Python) 코드 + 해설 (0) | 2024.10.31 |