1. 문제
재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름도 재현시로 변경했다. 이번 선거에서는 최대한 공평하게 선거구를 획정하려고 한다.
재현시는 크기가 N×N인 격자로 나타낼 수 있다. 격자의 각 칸은 구역을 의미하고, r행 c열에 있는 구역은 (r, c)로 나타낼 수 있다. 구역을 다섯 개의 선거구로 나눠야 하고, 각 구역은 다섯 선거구 중 하나에 포함되어야 한다. 선거구는 구역을 적어도 하나 포함해야 하고, 한 선거구에 포함되어 있는 구역은 모두 연결되어 있어야 한다. 구역 A에서 인접한 구역을 통해서 구역 B로 갈 수 있을 때, 두 구역은 연결되어 있다고 한다. 중간에 통하는 인접한 구역은 0개 이상이어야 하고, 모두 같은 선거구에 포함된 구역이어야 한다.
선거구를 나누는 방법은 다음과 같다.
- 기준점 (x, y)와 경계의 길이 d1, d2를 정한다. (d1, d2 ≥ 1, 1 ≤ x < x+d1+d2 ≤ N, 1 ≤ y-d1 < y < y+d2 ≤ N)
- 다음 칸은 경계선이다.
- (x, y), (x+1, y-1), ..., (x+d1, y-d1)
- (x, y), (x+1, y+1), ..., (x+d2, y+d2)
- (x+d1, y-d1), (x+d1+1, y-d1+1), ... (x+d1+d2, y-d1+d2)
- (x+d2, y+d2), (x+d2+1, y+d2-1), ..., (x+d2+d1, y+d2-d1)
- 경계선과 경계선의 안에 포함되어있는 곳은 5번 선거구이다.
- 5번 선거구에 포함되지 않은 구역 (r, c)의 선거구 번호는 다음 기준을 따른다.
- 1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y
- 2번 선거구: 1 ≤ r ≤ x+d2, y < c ≤ N
- 3번 선거구: x+d1 ≤ r ≤ N, 1 ≤ c < y-d1+d2
- 4번 선거구: x+d2 < r ≤ N, y-d1+d2 ≤ c ≤ N
구역 (r, c)의 인구는 A[r][c]이고, 선거구의 인구는 선거구에 포함된 구역의 인구를 모두 합한 값이다. 선거구를 나누는 방법 중에서, 인구가 가장 많은 선거구와 가장 적은 선거구의 인구 차이의 최솟값을 구해보자.
2. 입력
첫째 줄에 재현시의 크기 N이 주어진다.
둘째 줄부터 N개의 줄에 N개의 정수가 주어진다. r행 c열의 정수는 A[r][c]를 의미한다.
3. 출력
첫째 줄에 인구가 가장 많은 선거구와 가장 적은 선거구의 인구 차이의 최솟값을 출력한다.
4. 해결방법
이 문제는 구현, 완전탐색 문제이다. 기준점 x,y와 경계의 길이 d1,d2가 가질수 있는 모든 조합을 다 탐색해서 선거구끼리의 인구수 차이의 최소값을 구해주면된다. 각 변수들이 가질 수 있는 범위는 1~n 까지이고, 문제에서 제공한 변수의 조건만 만족하면 모두 후보가 될 수 있다. 모든 조합을 탐색하면서 cal함수를 실행시켜 최소값을 업데이트해주면된다.
1) cal 함수: 선거구당 인구수를 저장하는 elec배열과 각 좌표가 어떤 선거구인지를 알려주는 temp배열을 선언해준다. 입력값으로 들어온 x,y,d1,d2에 대해서 경계선에 해당하는 부분을 5번 선거구로 지정해준다. 그 다음 경계선 내부에 대해서는 행을 탐색하면서 경계선을 만나면 그 다음 경계선을 만날때까지 5번 선거구로 지정해주면되는데, 이는 bool값을 이용하여 구해줄 수 있다. 5번선거구를 구했으면, 5번선거구에 포함되지 않은 영역중 각 선거구의 범위에 해당하는 부분을 지정해주면된다.
5) 구현코드
def cal(x, y, d1, d2):
elec = [0 for i in range(5)] #선거구 당 인구수
temp = [[0] * (n + 1) for i in range(n + 1)] #선거구
#경계선을 5번 선거구로 할당
for i in range(d1 + 1):
temp[x + i][y - i] = 5 #1번조건
temp[x + d2 + i][y + d2 - i] = 5 #3번조건
for i in range(d2 + 1):
temp[x + i][y + i] = 5 #2번조건
temp[x + d1 + i][y - d1 + i] = 5 #4번조건
#경계선 내부를 5번 선거구로 할당
for i in range(x + 1, x + d1 + d2):
flag = False
#행기준으로 한번 경계구역을 만나면
for j in range(1, n + 1):
if temp[i][j] == 5:
flag = not flag #다시 경계구역만날때까지
if flag:
temp[i][j] = 5 #5번구역
for r in range(1, n + 1):
for c in range(1, n + 1):
if r < x + d1 and c <= y and temp[r][c] == 0:
elec[0] += graph[r][c] #1번선거구
elif r <= x + d2 and y < c and temp[r][c] == 0:
elec[1] += graph[r][c] #2번선거구
elif x + d1 <= r and c < y - d1 + d2 and temp[r][c] == 0:
elec[2] += graph[r][c] #3번선거구
elif x + d2 < r and y - d1 + d2 <= c and temp[r][c] == 0:
elec[3] += graph[r][c] #4번선거구
elif temp[r][c] == 5:
elec[4] += graph[r][c] #5번선거구
return max(elec) - min(elec) #선거구의 차이
n = int(input())
graph = [[]]
result = 1e9 #인구차이의 최소값
for i in range(n):
graph.append([0] + list(map(int, input().split())))
#완전탐색
for x in range(1, n + 1):
for y in range(1, n + 1):
for d1 in range(1, n + 1):
for d2 in range(1, n + 1):
if 1 <= x < x + d1 + d2 <= n and 1 <= y - d1 < y < y + d2 <= n:
result = min(result, cal(x, y, d1, d2))
print(result)
⭐️난이도: 골드 4 ⭐️
https://www.acmicpc.net/problem/17779
'Algorithms > Samsung' 카테고리의 다른 글
[python] BOJ 백준 20056: 마법사상어와 파이어볼 (0) | 2022.04.27 |
---|---|
[python] BOJ 백준 19237: 어른상어 (0) | 2022.04.27 |
[python] BOJ 백준 17140: 이차원배열과연산 (0) | 2022.04.26 |
[python] BOJ 백준 17143: 낚시왕 (0) | 2022.04.26 |
[python] BOJ 백준 21608: 상어 초등학교 (0) | 2022.04.26 |