[백준] 17779 게리맨더링 2
업데이트:
삼성 기출 게리맨터링2 문제 풀이입니다.
문제는 굉장히 직관적인 편이다. 문제에서 나온 조건 그대로 구현하면 되기 때문이다.
하지만 세세한 예외상황을 생각해보면 많이 복잡하고 어렵다는 것을 알 수 있다.
우선 최대 인구와 최소 인구의 차이가 최솟값인 것을 찾기 위해서는 DFS를 사용해야 했다. 모든 길이별로 DFS를 통해 완전탐색을 시킨 뒤 최솟값을 구하는 방식이기 때문이다.
DFS를 사용하여 각 선거구를 라벨링을 시킨 뒤 (여기에선 문제에서 나온 조건을 거의 그대로 구현하였다.) 선거구 인구수를 구해서 값을 구하였다. -> Labeling함수 참조
단, Chk함수를 통해 선거구가 될 수 없는 경우는 패스해줘야 한다. 오류가 나거나 시간이 초과될 수 있기 때문이다.
코드는 다음과 같습니다.
Source Code :
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
#define MAX 21
#define INF 987654321
int map[MAX][MAX]; // 나눌 선거구
int Person[MAX][MAX]; // 인구수
pair<int, int> Pos[4]; // 꼭지점 위 오 왼 아
int N, Answer = INF;
int Cal(int Num) {
int result = 0;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (map[i][j] == Num) {
result += Person[i][j];
}
}
}
return result;
}
bool Chk(int x,int y,int d1,int d2) {
if (x + d1 + d2 > N || x > x + d1 + d2) return false;
if (y - d1 > y || y - d1 < 1) return false;
if (y > y + d2) return false;
if (y + d2 > N)return false;
return true;
}
void Labeling(int x,int y,int d1,int d2) {
// Pos[0] up Pos[1] Right Pos[2] Left Pos[3] Down
// 1
int cnt = 0;
for (int i = 1; i < Pos[2].first; i++) {
if (i >= Pos[0].first) cnt++;
for (int j = 1; j <= Pos[0].second - cnt; j++) {
map[i][j] = 1;
}
}
// 2
cnt = 1;
for (int i = 1; i <= Pos[1].first; i++) {
if (i > Pos[0].first) cnt++;
for (int j = Pos[0].second + cnt; j <= N; j++) {
map[i][j] = 2;
}
}
//3
cnt = 0;
for (int i = N; i >= Pos[2].first; i--) {
if (i < Pos[3].first) cnt++;
for (int j = 1; j < Pos[3].second - cnt; j++) {
map[i][j] = 3;
}
}
//4
cnt = 0;
for (int i = N; i > Pos[1].first; i--) {
if (i <= Pos[3].first) cnt++;
for (int j = Pos[3].second+cnt; j <= N; j++) {
map[i][j] = 4;
}
}
}
void solve(int x, int y) { // 기준점 x, y
vector<int> Vote; // 인구수, 선거구
for (int d1 = 1; d1 <= y; d1++) { // d1 d2 길이
for (int d2 = 1; d2 < N; d2++) {
if (Chk(x, y, d1, d2)) {
Pos[0].first = x;
Pos[0].second = y;
Pos[1].first = x + d2;
Pos[1].second = y + d2;
Pos[2].first = x + d1;
Pos[2].second = y - d2;
Pos[3].first = x + d1 + d2;
Pos[3].second = y - d1 + d2;
Vote.clear();
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
map[i][j] = 5;
}
}
Labeling(x, y, d1, d2);
for (int i = 1; i <= 5; i++) {
Vote.push_back(Cal(i));
}
sort(Vote.begin(), Vote.end());
Answer = min(Answer, Vote[4] - Vote[0]);
}
}
}
}
int main() {
cin >> N;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cin >> Person[i][j];
}
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
solve(i, j);
}
}
cout << Answer;
system("pause");
return 0;
}
- 혹시 잘못된 부분이 있다면 댓글달아주세요! 감사합니당.
소스코드
이 외에도 제가 푼 문제들 소스코드는 다음 링크에 있습니다!!! 알고리즘 문제풀이
댓글남기기