https://www.acmicpc.net/problem/17471
17471번: 게리맨더링
선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.
www.acmicpc.net
풀이
문제를 보았을 때 알 수 있는 힌트
두개의 선거구로 나누어져야하고 2개이상으로 나누어지거나 선거구가 하나인 경우는 -1로 만들기만 하면 된다.
또한 그 둘의 차이가 최소인 값을 찾기위해 반복해서 돌리면 결과가 나온다!
조금 코드 짜는데 어려울수있지만 이해하면서 풀다보면 풀 수 있다.
package baekjoon17471;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[] people;
static int min;
static ArrayList<ArrayList<Integer>> list;
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(in.readLine());
people = new int[N + 1]; // 1 based
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int i = 1; i <= N; i++) {
int pp = Integer.parseInt(st.nextToken());
people[i] = pp;
}
// init list
list = new ArrayList<>();
for (int i = 0; i <= N; i++) {
list.add(new ArrayList<>());
}
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(in.readLine(), " ");
int cnt = Integer.parseInt(st.nextToken());
for (int j = 0; j < cnt; j++) {
int node = Integer.parseInt(st.nextToken());
list.get(i).add(node);
list.get(node).add(i);
}
}
// 모든 인구 수
int totalPeople = 0;
for(int i=1;i<=N;i++) {
totalPeople += people[i];
}
min = totalPeople;
subset(1, new boolean[N + 1]);
if(min == totalPeople) System.out.println(-1);
else System.out.println(min);
}
static void subset(int cnt, boolean[] isSelected) {
if (cnt == N + 1) {
boolean[] visited = new boolean[cnt];
int check = 0;
for (int i = 1; i < cnt; i++) {
if (!visited[i]) {
dfs(i, visited, isSelected);
check++;
}
}
if (check == 2) {
int sum1 = 0, sum2 = 0;
for (int i = 0; i < cnt; i++) {
if (isSelected[i])
sum1 += people[i];
else
sum2 += people[i];
}
int diff = Math.abs(sum1 - sum2);
min = Math.min(min, diff);
}
return;
}
isSelected[cnt] = true;
subset(cnt + 1, isSelected);
isSelected[cnt] = false;
subset(cnt + 1, isSelected);
}
static void dfs(int idx, boolean[] visited, boolean[] isSelected) {
if (idx > N)
return;
visited[idx] = true;
for (int i = 1; i <= N; i++) {
if (!visited[i] && isSelected[i] == isSelected[idx] && list.get(idx).contains(i)) {
dfs(i, visited, isSelected);
}
}
}
}
https://github.com/dydwkd486/coding_test/blob/main/baekjoon/java/baekjoon17471/Main.java
GitHub - dydwkd486/coding_test: 코딩테스트 공부한 내용 정리
코딩테스트 공부한 내용 정리. Contribute to dydwkd486/coding_test development by creating an account on GitHub.
github.com
'Coding Test > baekjoon' 카테고리의 다른 글
[백준 2512] 예산- java (solved.ac - 실버 3) (0) | 2022.09.19 |
---|---|
[백준 20055] 컨베이어 벨트 위의 로봇- java (solved.ac - 골드 5) (0) | 2022.09.18 |
[백준 1263] 시간 관리- java (solved.ac - 실버 1) (0) | 2022.09.14 |
[백준 1339] 단어 수학- python (solved.ac - 골드 4) (0) | 2022.09.11 |
[백준 16234] 인구 이동- python (solved.ac - 골드 5) (2) | 2022.09.10 |