일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 포스코 AI교육
- 초소형머신러닝
- 알고리즘
- tflite
- dfs
- BFS
- 삼성코딩테스트
- dfs문제
- 삼성역테
- TensorFlow Lite
- 컴퓨팅사고
- 다이나믹프로그래밍
- 코테 문제
- 코테
- 자료구조
- tinyml
- 삼성코테
- sort
- DP
- 포스코 교육
- bfs문제
- 코딩테스트
- 영상처리
- DP문제
- MCU 딥러닝
- 딥러닝
- 그리디
- 포스코 ai 교육
- 삼성역량테스트
- 임베디드 딥러닝
- Today
- Total
코딩뚠뚠
[삼성역량테스트] 17779 게리맨더링 2 본문
풀이일시 : 2021-04-02
문제 :
재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름도 재현시로 변경했다. 이번 선거에서는 최대한 공평하게 선거구를 획정하려고 한다.
재현시는 크기가 N×N인 격자로 나타낼 수 있다. 격자의 각 칸은 구역을 의미하고, r행 c열에 있는 구역은 (r, c)로 나타낼 수 있다. 구역을 다섯 개의 선거구로 나눠야 하고, 각 구역은 다섯 선거구 중 하나에 포함되어야 한다. 선거구는 구역을 적어도 하나 포함해야 하고, 한 선거구에 포함되어 있는 구역은 모두 연결되어 있어야 한다. 구역 A에서 인접한 구역을 통해서 구역 B로 갈 수 있을 때, 두 구역은 연결되어 있다고 한다. 중간에 통하는 인접한 구역은 0개 이상이어야 하고, 모두 같은 선거구에 포함된 구역이어야 한다.
선거구를 나누는 방법은 다음과 같다.
- 기준점 (x, y)와 경계의 길이 d1, d2를 정한다. (d1, d2 ≥ 1, 1 ≤ x < x+d1+d2 ≤ N, 1 ≤ y-d1 < y < y+d2 ≤ N)
- 다음 칸은 경계선이다.
- (x, y), (x+1, y-1), ..., (x+d1, y-d1)
- (x, y), (x+1, y+1), ..., (x+d2, y+d2)
- (x+d1, y-d1), (x+d1+1, y-d1+1), ... (x+d1+d2, y-d1+d2)
- (x+d2, y+d2), (x+d2+1, y+d2-1), ..., (x+d2+d1, y+d2-d1)
- 경계선과 경계선의 안에 포함되어있는 곳은 5번 선거구이다.
- 5번 선거구에 포함되지 않은 구역 (r, c)의 선거구 번호는 다음 기준을 따른다.
- 1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y
- 2번 선거구: 1 ≤ r ≤ x+d2, y < c ≤ N
- 3번 선거구: x+d1 ≤ r ≤ N, 1 ≤ c < y-d1+d2
- 4번 선거구: x+d2 < r ≤ N, y-d1+d2 ≤ c ≤ N
아래는 크기가 7×7인 재현시를 다섯 개의 선거구로 나눈 방법의 예시이다.
구역 (r, c)의 인구는 A[r][c]이고, 선거구의 인구는 선거구에 포함된 구역의 인구를 모두 합한 값이다. 선거구를 나누는 방법 중에서, 인구가 가장 많은 선거구와 가장 적은 선거구의 인구 차이의 최솟값을 구해보자.
입력 :
첫째 줄에 재현시의 크기 N이 주어진다.
둘째 줄부터 N개의 줄에 N개의 정수가 주어진다. r행 c열의 정수는 A[r][c]를 의미한다.
ex)
6
1 2 3 4 1 6
7 8 9 1 4 2
2 3 4 1 1 3
6 6 6 6 9 4
9 1 9 1 9 5
1 1 1 1 9 9
출력 :
첫째 줄에 인구가 가장 많은 선거구와 가장 적은 선거구의 인구 차이의 최솟값을 출력한다.
ex)
18
제한 :
- 5 ≤ N ≤ 20
- 1 ≤ A[r][c] ≤ 100
풀이 및 코드 :
복잡한 알고리즘이 들어가지는 않는 브루트포스이지만 조건문이 내기준 굉장히 까다로웠다.
한문제 푸는데 2시간 시간 초과..
#include <iostream>
#include <algorithm>
using namespace std;
int N;
int map[21][21] = { 0, }; //각 파트별 인구수를 넣어줄것이다.
int MIN = 987654321;
int part(int r, int c, int d1, int d2) { //각 파트별 넓이가 얼마인지 구하고 최소를 리턴
int l1 = c + 1;
int l2 = r + d1;
int l3 = c - (d1 - d2);
int l4 = r + d2 + 1;
int number[5] = { 0, };
for (int i = 1; i <=N; i++) {
for (int j = 1; j<= N; j++) {
if (i < l2 && j <= c && !(i >= r && j >= c - (i - r))) { //1번구역
number[0] += map[i][j];
}
else if (i<l4 && j>c && !(i >= r && j <= c + (i - r))) { //2번구역
number[1] += map[i][j];
}
else if (i >= l2 && j < l3 && !(i <= r + d1 + d2 && j >= (c - d1 + d2 - (r + d1 + d2 - i)))) { //3번구역
number[2] += map[i][j];
}
else if (i >= l4 && j >= l3 && !(i <= r + d1 + d2 && j <= (c - d1 + d2 + (r + d1 + d2 - i)))) { //4번구역
number[3] += map[i][j];
}
else { //5번구역
number[4] += map[i][j];
}
}
}
sort(number, number + 5);
int min = number[0];
int max = number[4];
int res = max - min;
return res;
}
int solution() { //BF
for (int i = 1; i <= N-2; i++) { //시작점이 밑으로로 한칸씩 이동
for (int j = 2; j <= N-1; j++) { //시작점이 오른쪽으로 한칸씩 이동
//시작점을 짚은 이후의 d설정
for (int d1 = 1; d1 <= j-1 && d1 <= N - i-1; d1++) { //d1설정
for (int d2 = 1; d2 <= N - j && d2 <= N - i-1; d2++) { //d2설정
int result = part(i, j, d1, d2);
if (result <= MIN) {
MIN = result;
}
}
}
}
}
return MIN;
}
int main() {
int s;
cin >> N;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cin >> s;
map[i][j] = s;
}
}
cout << solution() << '\n';
return 0;
}
'알고리즘 문제풀이 > 삼성역량테스트' 카테고리의 다른 글
[삼성역량테스트] 17143 낚시왕 (0) | 2021.04.21 |
---|---|
[삼성역량테스트] 17140 이차원 배열과 연산 (0) | 2021.04.20 |
[삼성역량테스트] 17837 새로운 게임 2 (0) | 2021.03.19 |
[삼성역량테스트] 17822 원판돌리기 (0) | 2021.03.18 |
[삼성역량테스트] 17825 주사위윷놀이 (0) | 2021.03.14 |