본문 바로가기

알고리즘(Algorithm)

[C++] 게리맨더링2 (17779번)

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

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름도

www.acmicpc.net


문제풀이

개인적으로 상성이 너무 안맞는 문제다. 2차원 배열의 인덱스를 잘 조절하여 만복문을 돌리는건데 덧셈 뺄셈이 너무 헷갈려 죽는줄 알았다.

 

조건을 보면 사각형 모양의 테두리는 반드시 생겨야 한다.

시작지점 행 열을 0으로 두고 풀었다.

 

그러므로 열의 시작지점은 반드시 1부터 n-2 사이 이어야 한다.

행의 시작지점은 0부터 n-3까지 이어야 한다. 그래야 사각형이 만들어진다.

그리고 d1은 현재 열 인덱스 값보다 작거나 같아야 하고, d2는 n-현재열보다 작거나 같아야 한다. 그래야 양 끝이 배열을 넘지 않는다. 그리고 d1+d2+현재행의 값이 n보다 크면 안된다.

이 조건을 만족하는 모든 값들을 반복문 돌리면 된다.

난 1, 2, 3, 4 구역을 구하고 5구역은 총합에서 네 구역 값을 빼는 방식으로 구했다.

 

모두 행을 기준으로 반복을 돌도록 하였다.

현재 행을 i, 열을 j라고 한다.

1구역의 행은 0~i+d1이다. 1구역의 열은 상황에 따라 다른데, i>r이면 열은 0~j까지다. 그게 아니라면, 행을 내려가며 열 계산하는 부분을 1씩 빼주면 된다.

말로하니 굉장히 어려운데 실제로도 계산하는데 머리 터지는줄 알았다. 이런 방법으로 4구역을 모두 계산해 값을 정리하면 된다. 이거 계산하는게 정말 .... 쉽지않다.

 

#include <iostream>

using namespace std;

int n;
int arr[100][100];

int main() {
    cin >> n;
    int sum = 0;
    for(int i=0; i<n; i++) {
        for(int j=0; j<n; j++) {
            cin >> arr[i][j];
            sum += arr[i][j];
        }
    }

    int answer = 999999999;

    for(int i=0; i<n-2; i++) {
        for(int j=1; j<n-1; j++) {
            for(int d1=1; j-d1>=0; d1++) {
                for(int d2=1; n-j-d2>0; d2++) {
                    if(n-(i+d1+d2)<=0) continue;
                    int min_value = 999999999;
                    int max_value = 0;
                    int arr5 = sum;
                    // cout << i << " " << j << endl;

                    // 1구역
                    int cnt = 0;
                    for(int r=0; r<i+d1; r++) {
                        int tmp;
                        if(i>r) tmp = 0;
                        else tmp = r-i+1;
                        // cout << "aa " << r << " " << tmp << endl;
                        for(int c=0; c<=j-tmp; c++) {
                            cnt += arr[r][c];
                        }
                    }
                    min_value = min(min_value, cnt);
                    max_value = max(max_value, cnt);
                    arr5 -= cnt;
                    // cout << cnt << " ";

                    // 2구역
                    cnt = 0;
                    for(int r=0; r<=i+d2; r++) {
                        int tmp;
                        if(i>=r) tmp = 0;
                        else tmp = r-i;
                        // cout << "aa " << i << " " << r << " " << tmp << endl;
                        for(int c=j+1+tmp; c<n; c++) {
                            cnt += arr[r][c];
                        }
                    }
                    min_value = min(min_value, cnt);
                    max_value = max(max_value, cnt);
                    arr5 -= cnt;
                    // cout << cnt << " ";

                    // 3구역
                    cnt = 0;
                    for(int r=i+d1; r<n; r++) {
                        int tmp;
                        if(r>=i+d1+d2) tmp = d2;
                        else tmp = r-(i+d1);
                        for(int c=0; c<j-d1+tmp; c++) {
                            cnt += arr[r][c];
                        }
                    }
                    min_value = min(min_value, cnt);
                    max_value = max(max_value, cnt);
                    arr5 -= cnt;
                    // cout << cnt << " ";

                    // 4구역
                    cnt = 0;
                    for(int r=i+d2+1; r<n; r++) {
                        int tmp;
                        if(r>i+d1+d2) tmp = d1;
                        else tmp = r-(i+d2+1);
                        // cout << "aa " << i << " " << r << " " << tmp << endl;
                        for(int c=j+d2-tmp; c<n; c++) {
                            cnt += arr[r][c];
                        }
                    }
                    min_value = min(min_value, cnt);
                    max_value = max(max_value, cnt);
                    arr5 -= cnt;
                    // cout << cnt << " ";

                    // 5구역
                    min_value = min(min_value, arr5);
                    max_value = max(max_value, arr5);
                    // cout << arr5 << endl;

                    answer = min(answer, max_value-min_value);

                    // return 0;
                }
            }
        }
    }
    cout << answer;
    return 0;
}

 

 

'알고리즘(Algorithm)' 카테고리의 다른 글

[C++] 문제집 (1766번) 위상 정렬  (0) 2023.10.19
[C++] 수열 (2491번)  (0) 2023.10.18
[C++] 낚시왕 (17143번)  (1) 2023.10.14
[C++] 나무 재테크 (16235번)  (0) 2023.10.13
[C++] 사다리 조작 (15684번)  (2) 2023.10.11