홍시홍의 프로그래밍

[백준 17779] 게리멘더링 2 본문

알고리즘 문제풀이/백준

[백준 17779] 게리멘더링 2

홍시홍 2020. 2. 1. 16:32

https://www.acmicpc.net/problem/17779

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름도 재현시로 변경했다. 이번 선거에서는 최대한 공평하게 선거구를 획정하려고 한다. 재현시는 크기가 N×N인 격자로 나타낼 수 있다. 격자의 각 칸은 구역을 의미하고, r행 c열에 있는 구역은 (r, c)로 나타낼 수 있다. 구역을 다섯 개의 선거구로 나눠야 하고, 각 구역은 다

www.acmicpc.net

요구사항

구역별 선거인원들의 합의 최대값과 최소값이 최소가 되도록 구역 나누기

 

풀이

1. x, y, d1, d2 정하기

2. 5번 라인 긋기

3. 1, 2, 3, 4구역 정하기

4. 각 구역의 합 구하기

5. 최소, 최대 구하기

6. 정답 구하기

 

아주 브루트 포스 스러운 문제이다.

 

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
int map[21][21];
int visit[21][21];
int n;
bool check(int r, int c, int d1, int d2) {
	if (d1 >= 1 && d2 >= 1) {
		if (r + d1 + d2 <= n) {
			if (1 <= c - d1) {
				if (c + d2 <= n) {
					return true;
				}
			}
		}
	}
	return false;
}
void line(int r, int c, int d1, int d2) {
	for (int i = 0; i <= d1; i++) {
		visit[r + i][c - i] = 5;
		visit[r + d2 + i][c + d2 - i] = 5;
	}

	for (int i = 0; i <= d2; i++) {
		visit[r + i][c + i] = 5;
		visit[r + d1 + i][c - d1 + i] = 5;
	}


}

void num1(int r, int c, int d1, int d2) {
	for (int i = 1; i < r + d1; i++) {
		for (int j = 1; j <= c; j++) {
			if (visit[i][j] == 5)
				break;
			else {
				visit[i][j] = 1;
			}
		}
	}
}
void num2(int r, int c, int d1, int d2) {
	for (int i = 1; i <= r + d2; i++) {
		for (int j = n; j > c; j--) {
			if (visit[i][j] == 5)
				break;
			else {
				visit[i][j] = 2;
			}
		}
	}
}

void num3(int r, int c, int d1, int d2) {
	for (int i = r+d1; i <= n; i++) {
		for (int j = 1; j < c-d1+d2; j++) {
			if (visit[i][j] == 5)
				break;
			else {
				visit[i][j] = 3;
			}
		}
	}
}

void num4(int r, int c, int d1, int d2) {
	for (int i = r + d2+1; i <= n; i++) {
		for (int j = n; j >= c - d1 + d2; j--) {
			if (visit[i][j] == 5)
				break;
			else {
				visit[i][j] = 4;
			}
		}
	}
}
int sum[6];
int maxv = 0;
int minv = 987654321;
int ans = 987654321;
void cal() {
	maxv = 0;
	minv = 987654321;
	memset(sum, 0, sizeof(sum));
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (visit[i][j] == 1) {
				sum[1] += map[i][j];
			}
			else if (visit[i][j] == 2) {
				sum[2] += map[i][j];
			}
			else if (visit[i][j] == 3) {
				sum[3] += map[i][j];
			}
			else if (visit[i][j] == 4) {
				sum[4] += map[i][j];
			}
			else if (visit[i][j] == 5 || visit[i][j]==0) {
				sum[5] += map[i][j];
			}
		}
	}
	for (int i = 1; i <= 5; i++) {
		maxv = max(sum[i], maxv);
		minv = min(sum[i], minv);
	}
	int tempans = maxv - minv;
	ans = min(tempans, ans);
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> map[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			for (int d1 = 1; d1 < n; d1++) {
				for (int d2 = 1; d2 < n; d2++) {
					if (check(i, j, d1, d2)) {
						memset(visit, 0, sizeof(visit));
						memset(sum, 0, sizeof(sum));
						line(i, j, d1, d2);
						num1(i, j, d1, d2);
						num2(i, j, d1, d2);
						num3(i, j, d1, d2);
						num4(i, j, d1, d2);
						cal();
					}

				}
			}
		}
	}

	cout << ans << endl;
}

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 14500] 테트로미노  (0) 2020.02.02
[백준 14499] 주사위 굴리기  (0) 2020.02.02
[백준 13458] 시험감독  (0) 2020.01.31
[백준 3190] 뱀  (0) 2020.01.31
[백준 17822] 원판 돌리기  (0) 2020.01.30
Comments