ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 - 게리맨더링 2 (17779) [C++]
    문제 풀이/백준 2023. 3. 27. 10:42
    반응형

     이 문제는 브루트 포스, 시뮬레이션 문제이다. 이 문제는 좌표를 잘 보고 구역을 잘 나누는 것이 중요하다. 또한 처음에는 경계선의 가능 여부를 재귀를 통해 만들었는데, 이는 시간 초과가 발생한다. 그래서 d1과 d2의 범위를 찾아내고, 그 안에서 y와 x를 루프를 돌아 경계선을 만들면 시간 초과가 발생하지 않는다. 

     

     

     

    #include <iostream>
    #include <vector>
    #include <utility>
    #include <algorithm>
    using namespace std;
    
    #define MAX 30
    
    typedef struct _node
    {
    	int y;
    	int x;
    	int d1;
    	int d2;
    } node;
    
    int n;
    int people[30][30];
    vector<node> divs;
    
    void divideSection(int y, int x, int d1, int d2)
    {
    	if (1 <= y && y < y + d1 + d2 && y + d1 + d2 <= n &&
    		1 <= x - d1 && x - d1 < x && x < x + d2 && x + d2 <= n)
    	{
    		divs.push_back({ y, x, d1, d2 });
    	}
    }
    
    int section5(vector<vector<int>> &temp, node& div)
    {
    	int result = 0;
    
    	// 경계선 만들기
    	for (int y = div.y, x = div.x; y <= div.y + div.d1 && x >= div.x - div.d1; y++, x--)
    	{
    		temp[y][x] = 5;
    	}
    
    	for (int y = div.y, x = div.x; y <= div.y + div.d2 && x <= div.x + div.d2; y++, x++)
    	{
    		temp[y][x] = 5;
    	}
    
    	for (int y = div.y + div.d1, x = div.x - div.d1; y <= div.y + div.d1 + div.d2 && x <= div.x - div.d1 + div.d2; y++, x++)
    	{
    		temp[y][x] = 5;
    	}
    
    	for (int y = div.y + div.d2, x = div.x + div.d2; y <= div.y + div.d2 + div.d1 && x >= div.x + div.d2 - div.d1; y++, x--)
    	{
    		temp[y][x] = 5;
    	}
    
    	// 내부 채우기
    	for (int y = 1; y <= n; y++)
    	{
    		bool toggle = false;
    		for (int x = 1; x <= n; x++)
    		{
    			if ((y == div.y || y == div.y + div.d1 + div.d2) &&
    				temp[y][x] == 5)
    			{
    				result += people[y][x];
    			}
    			else if (div.y < y && y < div.y + div.d1 + div.d2)
    			{
    				if (!toggle && temp[y][x] == 5)
    				{
    					toggle = true;
    					result += people[y][x];
    				}
    				else if (toggle && temp[y][x] != 5)
    				{
    					temp[y][x] = 5;
    					result += people[y][x];
    				}
    				else if (toggle && temp[y][x] == 5)
    				{
    					toggle = false;
    					result += people[y][x];
    				}
    			}
    		}
    	}
    
    	return result;
    }
    
    int section1(vector<vector<int>> &temp, node &div)
    {
    	int result = 0;
    
    	for (int y = 1; y < div.y + div.d1; y++)
    	{
    		for (int x = 1; x <= div.x; x++)
    		{
    			if (temp[y][x] == 5)
    			{
    				continue;
    			}
    			temp[y][x] = 1;
    			result += people[y][x];
    		}
    	}
    
    	return result;
    }
    
    int section2(vector<vector<int>> &temp, node &div)
    {
    	int result = 0;
    
    	for (int y = 1; y <= div.y + div.d2; y++)
    	{
    		for (int x = div.x + 1; x <= n; x++)
    		{
    			if (temp[y][x] == 5)
    			{
    				continue;
    			}
    			temp[y][x] = 2;
    			result += people[y][x];
    		}
    	}
    
    	return result;
    }
    
    int section3(vector<vector<int>> &temp, node &div)
    {
    	int result = 0;
    
    	for (int y = div.y + div.d1; y <= n; y++)
    	{
    		for (int x = 1; x < div.x - div.d1 + div.d2; x++)
    		{
    			if (temp[y][x] == 5)
    			{
    				continue;
    			}
    			temp[y][x] = 3;
    			result += people[y][x];
    		}
    	}
    
    	return result;
    }
    
    int section4(vector<vector<int>> &temp, node &div)
    {
    	int result = 0;
    
    	for (int y = div.y + div.d2 + 1; y <= n; y++)
    	{
    		for (int x = div.x - div.d1 + div.d2; x <= n; x++)
    		{
    			if (temp[y][x] == 5)
    			{
    				continue;
    			}
    			temp[y][x] = 4;
    			result += people[y][x];
    		}
    	}
    
    	return result;
    }
    
    int main()
    {
    	ios_base::sync_with_stdio(0);
    	cin.tie(0);
    
    	cin >> n;
    
    	// 입력 및 선거구 나누는 방법 만들기
    	for (int y = 1; y <= n; y++)
    	{
    		for (int x = 1; x <= n; x++)
    		{
    			cin >> people[y][x];
    
    			for (int d1 = 1; d1 <= x - 1; d1++)
    			{
    				for (int d2 = 1; d2 <= n - x; d2++)
    				{
    					divideSection(y, x, d1, d2);
    				}
    			}
    		}
    	}
    
    	int answer = INT32_MAX;
    	for (auto& div : divs)
    	{
    		vector<vector<int>> temp(n + 1, vector<int>(n + 1, 0));
    		int maxPeople = -1;
    		int minPeople = INT32_MAX;
    		int tempPeople;
    
    		// 5번 구역 만들기
    		tempPeople = section5(temp, div);
    		maxPeople = max(maxPeople, tempPeople);
    		minPeople = min(minPeople, tempPeople);
    
    		// 1번 구역 만들기
    		tempPeople = section1(temp, div);
    		maxPeople = max(maxPeople, tempPeople);
    		minPeople = min(minPeople, tempPeople);
    
    		// 2번 구역 만들기
    		tempPeople = section2(temp, div);
    		maxPeople = max(maxPeople, tempPeople);
    		minPeople = min(minPeople, tempPeople);
    
    		// 3번 구역 만들기
    		tempPeople = section3(temp, div);
    		maxPeople = max(maxPeople, tempPeople);
    		minPeople = min(minPeople, tempPeople);
    
    		// 4번 구역 만들기
    		tempPeople = section4(temp, div);
    		maxPeople = max(maxPeople, tempPeople);
    		minPeople = min(minPeople, tempPeople);
    
    		answer = min(answer, maxPeople - minPeople);
    	}
    
    	cout << answer << '\n';
    	
    	return 0;
    }
    반응형

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

    백준 - 2146 [C++]  (0) 2023.07.18
    백준 - 9019 [C++]  (0) 2023.07.18
    백준 - 낚시왕 (17143) [C++]  (0) 2023.03.26
    백준 - 톱니바퀴 (14891) [C++]  (0) 2023.03.26
    백준 - 2048 (Easy) (12100) [C++]  (2) 2023.03.25
Designed by Tistory.