난이도 : ●●○ | 풀이 시간 : 40분 | 시간 제한 : 2초 | 메모리 제한 : 512MB | 기출 : 삼성전자 SW 역량테스트
문제
- NxN 크기의 땅이 있고, 땅은 1x1개의 칸을 차지한다.
- 각 땅에는 나라가 하나씩 존재한다.
- r행 c열에 있는 나라의 인구수는 A[r][c]이다.
- 인접한 나라 사이에는 국경선이 있다.
- 오늘부터 인구이동이 시작된다.
- 국경선을 공유하는 나라의 인구 차이가 L이상 R이하라면 두 나라가 공유하는 국경선을 오늘 하루 동안 연다.
- 위 조건에 의해 열어야 하는 국경선이 모두 열리면 인구 이동을 시작한다.
- 국경선이 열려있어 이동할 수 있으면 그 나라를 오늘 하루 동안 연합이라고 한다.
- 연합을 이루는 각 나라의 인구수는 (연합의 인구수)/(연합을 이루고 있는 나라의 개수)가 되고, 편의상 소수점은 버린다.
- 연합을 해체하고 모든 국경선을 닫는다.
- 각 나라의 인구수가 주어질 때 인구 이동이 몇 번 발생하는지 구하는 프로그램을 작성하라.
입력조건
- 첫째 줄에 N, L, R이 주어진다.(1<=N<=50, 1<=L<=R<=100)
- 둘째 줄부터 N개의 줄에 각 나라의 인구수가 주어진다. r행 c열에 주어지는 정수는 A[r][c]의 값이다. ()<=A[r][c]<=100)
- 인구 이동 횟수가 2,000번보다 작거나 같은 입력만 주어진다.
출력조건
- 인구 이동이 몇 번 발생하는지 첫째 줄에 출력한다.
입력예시
2 20 50 50 30 20 40
출력예시
1
아이디어
- BFS로 상하좌우로 인접한 나라를 탐색하면서 연합국의 수, 연합의 총 인구수를 증가시킨다.
- 연합에 소속된 모든 나라의 인구수를 (연합의 총인원//연합국의 수)로 갱신한다.
코드
from collections import deque n,l,r = map(int,input().split()) graph = [] for _ in range(n): graph.append(list(map(int,input().split()))) dx = [-1,1,0,0] dy = [0,0,-1,1] total_cnt = 0 def bfs(index,x,y): q = deque() q.append((x,y)) # 연합을 생성함 unite = [] # 연합에 현재 국가를 추가함 unite.append((x,y)) # 연합번호를 union 리스트에 저장함 union[x][y]=index # unite에 소속된 국가의 개수 cnt = 1 # unite에 소속된 연합국가의 총 인구수 summary = graph[x][y] while q: x,y = q.popleft() for i in range(4): nx = x+dx[i] ny = y+dy[i] # 범위 내에 있고 아직 연합에 소속되지 않은 국가라면 if 0<=nx<n and 0<=ny<n and union[nx][ny]==-1: # 인접한 국가와의 인구수 차이가 l이상 r이하라면 if l<=abs(graph[x][y]-graph[nx][ny])<=r: # 큐에 추가함 q.append((nx,ny)) # 연합번호를 기록함 union[nx][ny] = index # 총 인구수를 증가시킴 summary+=graph[nx][ny] # unite에 소속된 국가의 수를 1 증가시킴 cnt += 1 # 연합에 추가함 unite.append((nx,ny)) # 연합에 소속된 국가들에 대해서 for i,j in unite: # 인구수를 업데이트함 graph[i][j] = summary//cnt while True: # 각 국가들이 소속된 연합번호를 기록할 리스트. # 방문여부를 확인하는 데에 사용됨 union = [[-1]*n for _ in range(n)] # 처음 생성되는 연합의 번호는 0 index = 0 # 아직 아무런 연합에 소속되지 않은 국가라면 그 위치에서부터 bfs를 수행함 # 한 연합이 생성된 것이니 연합번호인 index를 1 증가시킴 for i in range(n): for j in range(n): if union[i][j]==-1: bfs(index,i,j) index +=1 # 연합이 n*n개가 생성되었다 == 더이상 인구이동이 없다는 뜻이므로 반복 종료 if index==n*n: break # 인구이동 횟수를 1 증가시킴 total_cnt +=1 print(total_cnt)
후기
- 상하좌우로 인접해있는 나라가 연합이 될 수 있다는 걸 한 연합의 크기가 최대 5라는 것으로 잘못 이해했다...
- 더이상 이동이 일어나지 않을 때까지 반복한다는 걸 어떻게 구현해야 하는지 감을 못잡았다.
출처
이것이 취업을 위한 코딩테스트다 with 파이썬
'Algorithm > [이코테] 알고리즘 유형별 기출문제' 카테고리의 다른 글
[이코테] 다이나믹 프로그래밍 문제 - 퇴사 python (0) | 2023.11.24 |
---|---|
[이코테] 다이나믹 프로그래밍 - 정수 삼각형 python (1) | 2023.11.24 |
[이코테] 정렬 문제 - 실패율 python (0) | 2023.11.05 |
[이코테] 정렬 문제 - 안테나 python (0) | 2023.11.05 |
[이코테] 정렬 문제 - 국영수 python (0) | 2023.11.04 |