알고리즘/BAEKJOON
[백준] 17779 게리맨더링2 (Java)
kyeee2
2022. 6. 3. 15:31
[17779 게리맨더링2]
난이도: 골드4
17779번: 게리맨더링 2
재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름
www.acmicpc.net
문제
입력
출력
[아이디어]
가능한 모든 경우들을 완탐으로 풀었다.
1, 2, 3, 4번 선거구역을 나눠주고 해당되지 않는 구역을 5번 구역으로 판단해서 값을 구해줬다.
여기서 선거구역을 나눌 때 경계선의 꼭지점들을 기준으로 판단해주었다.
예를 들면, x = 4, y = 3, d1 = 1, d2 = 1 의 경우
1번 선거구역을 찾기 위해 (x, y) => (4, 3) 을 기준으로 위에 있는 칸들을 먼저 찾아주고
r이 3이하인 경우에는 가로의 길이를 하나씩 줄여서 (x + d1, y-d1) => (5, 2) 위까지 찾아주었다.
위의 설명을 코드로 구현하면 아래와 같다.
for(int r = 1, C = y; r < x + d1; r++) {
if(r >= x) {
C--;
}
for(int c = 1; c <= C; c++) {
sum += A[r][c];
}
}
2번 선거 구역은 (x + d2, y + d2) => (5, 4) 를 기준으로 오른쪽에 있는 칸들을 먼저 찾아주고
c가 4이하인 경우에는 높이를 하나씩 줄여서 (x, y) => (4, 3) 오른쪽까지 찾아주었다.
위의 설명을 코드로 구현하면 아래와 같다.
for(int c = N, R = x + d2; c > y; c--) {
if(c <= y + d2) {
R--;
}
for(int r = 1; r <= R; r++) {
sum += A[r][c];
}
}
이런 방식으로 3, 4번 구역도 찾아주었다.
그 다음엔 문제에 나와있듯이 가장 많은 인구수에서 가장 적은 인구수를 뺀 최솟값을 찾아주었다.
[JAVA 코드]
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokens;
static int N, total, minDiff = Integer.MAX_VALUE;
static int [][] A;
public static void main(String[] args) throws NumberFormatException, IOException {
N = Integer.parseInt(br.readLine());
A = new int [N + 1][N + 1];
for(int r = 1; r <= N; r++) {
tokens = new StringTokenizer(br.readLine());
for(int c = 1; c <= N; c++) {
A[r][c] = Integer.parseInt(tokens.nextToken());
total += A[r][c];
}
}
for(int x = 1; x <= N; x++) {
for(int y = 1; y <= N; y++) {
for(int d1 = 1; ; d1++) {
if(y - d1 < 1) break;
for(int d2 = 1; ; d2++) {
if(x + d1 + d2 > N || y + d2 > N) break;
calcSub(x, y, d1, d2);
}
}
}
}
System.out.println(minDiff);
}
private static void calcSub(int x, int y, int d1, int d2) {
int max = -1;
int min = Integer.MAX_VALUE;
int area5 = total;
// 1번 선거구역
int sum = 0;
for(int r = 1, C = y; r < x + d1; r++) {
if(r >= x) {
C--;
}
for(int c = 1; c <= C; c++) {
sum += A[r][c];
}
}
max = Math.max(max, sum);
min = Math.min(min, sum);
area5 -= sum;
// 2번 선거구역
sum = 0;
for(int c = N, R = x + d2; c > y; c--) {
if(c <= y + d2) {
R--;
}
for(int r = 1; r <= R; r++) {
sum += A[r][c];
}
}
max = Math.max(max, sum);
min = Math.min(min, sum);
area5 -= sum;
// 3번 선거구역
sum = 0;
for(int c = 1, R = x + d1; c < y - d1 + d2; c++) {
if(c >= y - d1) {
R++;
}
for(int r = R; r <= N; r++) {
sum += A[r][c];
}
}
max = Math.max(max, sum);
min = Math.min(min, sum);
area5 -= sum;
// 4번 선거구역
sum = 0;
for(int r = N, C = y - d1 + d2; r > x + d2; r--) {
if(r <= x + d1 + d2) {
C++;
}
for(int c = C; c <= N; c++) {
sum += A[r][c];
}
}
max = Math.max(max, sum);
min = Math.min(min, sum);
area5 -= sum;
// 5번 선거구역
max = Math.max(max, area5);
min = Math.min(min, area5);
minDiff = Math.min(minDiff, max - min);
}
}