ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 17779 게리맨더링2
    Algorithm/구현(Brute force, Back tracking, etc.) 2021. 11. 30. 19:51
    728x90

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

     

    17779번: 게리맨더링 2

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

    www.acmicpc.net

     

    - 브루트포스 + 빡구현 문제이다.

     

    - 시간복잡도는, 최악의 경우 거의 O(N^6)까지도 도달할 수 있다. 하지만 N의 최대값이 20이므로 1억 이하이기 때문에 해당 알고리즘으로 통과가 가능하다.

     

    - 시작점 x,y와 모든 d1, d2에 대한 경우의 수들을 선택해서 계산을 해야 한다. 4중 for문으로 4가지 변수값을 선택했다면, area 배열에 구역을 입력 해 주면 된다. 일단

     

      1. 5번 경계점들을 넣어주고,

      2. 경계선 내부를 5로 채워주고

      3. 차례대로 나머지 구역들을 채워준다.

     

      여기서, 경계선 내부를 채워주는 연산을 잘 해야 하는데 왼쪽 위, 오른쪽 위는 y값을 기준으로, 왼쪽 아래, 오른쪽 아래는 y-d1+d2값을 기준으로 해서 5를 잘 채워주면 된다.

     

    - 5번 구역만 잘 채워주면 쉽게 해결할 수 있는 문제이다. 

     

     

     

    #include <iostream>
    #include <string.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int man[21][21];
    int area[21][21];
    int n;
    
    int getpartOne(int x, int y, int d1, int d2) {
    	int sum = 0;
    	for (int i = 1; i < x + d1; i++) {
    		for (int j = 1; j <= y; j++) {
    			if (area[i][j] == 5) continue;
    			sum += man[i][j];
    		}
    	}
    	return sum;
    }
    int getpartTwo(int x, int y, int d1, int d2) {
    	int sum = 0;
    	for (int i = 1; i <= x + d2; i++) {		
    		for (int j = y + 1; j <= n; j++) {	
    			if (area[i][j] == 5) continue;
    			sum += man[i][j];
    		}
    	}
    	return sum;
    }
    int getpartThree(int x, int y, int d1, int d2) {
    	int sum = 0;
    	for (int i = x + d1; i <= n; i++) {		
    		for (int j = 1; j < y - d1 + d2; j++) {
    			if (area[i][j] == 5) continue;
    			sum += man[i][j];
    
    		}
    	}
    	return sum;
    }
    int getpartFour(int x, int y, int d1, int d2) {
    	int sum = 0;
    	for (int i = x + d2 + 1; i <= n; i++) {
    		for (int j = y - d1 + d2; j <= n; j++) {
    			if (area[i][j] == 5) continue;
    			sum += man[i][j];
    		}
    	}
    	return sum;
    }
    void divide(int x, int y, int d1, int d2) {
    	memset(area, 0, sizeof(area));
    	area[x][y] = 5;
    	//1
    	int nx = x;
    	int ny = y;
    	for (int i = 0; i < d1; i++) {
    		nx += 1; ny -= 1;
    		if (nx < 1 || nx > n || ny < 1 || ny > n) continue;
    		for (int j = ny; j <= y; j++) {
    			area[nx][j] = 5;
    		}
    	}
    	//2
    	nx = x;
    	ny = y;
    	for (int k = 0; k < d2; k++) {
    		nx += 1; ny += 1;
    		if (nx < 1 || nx > n || ny < 1 || ny > n) continue;
    		for (int j = y; j <= ny; j++) {
    			area[nx][j] = 5;
    		}
    	}
    	//3
    	nx = x + d1;
    	ny = y - d1;
    	area[nx][ny] = 5;
    	for (int k = 0; k < d2; k++) {
    		nx += 1; ny += 1;
    		area[nx][ny] = 5;
    		for(int j = ny; j <= y - d1 + d2; j++){
    			area[nx][j] = 5;
    		}
    	}
    	nx = x + d2;
    	ny = y + d2;
    	area[nx][ny] = 5;
    	for (int k = 0; k < d1; k++) {
    		nx += 1; ny -= 1;
    		if (nx < 1 || nx > n || ny < 1 || ny > n) continue;
    		for (int j = y-d1+d2; j <= ny; j++) {
    			area[nx][j] = 5;
    		}
    	}
    }
    int main() {
    	cin >> n;
    	int total_arr = 0;
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= n; j++) {
    			cin >> man[i][j];
    			total_arr += man[i][j];
    		}
    	}
    	//각 칸을 돌면서 기준점 정함
    	int answer = 2100000000;
    	for (int x = 1; x <= n; x++) {		//행
    		for (int y = 1; y <= n; y++) {		//열
    			for (int d1 = 1; d1 <= 20; d1++) {
    				for (int d2 = 1; d2 <= 20; d2++) {
    					if (x + d1 + d2 > n || y-d1<1 || y+d2 >n) break;
    					divide(x, y, d1, d2);
    					
    					int sum1 = getpartOne(x, y, d1, d2);
    					int sum2 = getpartTwo(x, y, d1, d2);
    					int sum3 = getpartThree(x, y, d1, d2);
    					int sum4 = getpartFour(x, y, d1, d2);
    					int sum5 = total_arr - (sum1 + sum2 + sum3 + sum4);
    					//각 선거구역 크기는 최소 1칸 이상
    					if (sum1 >= 1 && sum2 >= 1 && sum3 >= 1 && sum4 >= 1 && sum5 >= 1) {
    						vector<int> sum_of_area = { sum1, sum2, sum3, sum4, sum5 };
    						sort(sum_of_area.begin(), sum_of_area.end());
    						answer = min(answer, sum_of_area[4] - sum_of_area[0]);
    					}
    
    				}
    			}
    		}
    	}
    	cout << answer;
    	return 0;
    }

    'Algorithm > 구현(Brute force, Back tracking, etc.)' 카테고리의 다른 글

    백준 19237 어른 상어  (0) 2021.12.16
    백준 17822 원판 돌리기  (0) 2021.12.01
    백준 17142 연구소3  (0) 2021.11.26
    백준 17143 낚시왕  (0) 2021.11.26
    백준 17144 미세먼지 안녕!  (0) 2021.11.19

    댓글

Designed by Tistory.