250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- java
- 알고리즘
- 백준15652
- 삼성역테
- 완전탐색
- D드라이브생성
- 전화번호속의암호
- 알고리즘개념
- 중복순열
- 중복조합
- 파티션 크기 조정
- 정올 1620
- Bfs와DFS
- 에라토스테네스의채
- 주사위굴리기2
- 백준
- 자바
- N과M
- 코테준비
- 완탐
- 23288
- 순열
- 백준2251
- 자바 코테
- 백준13458
- 정보처리기사
- 재귀함수
- 코테
- 볼륨 만들기
- BFS
Archives
- Today
- Total
뚱땅뚱땅
[문제] 백준 17471번 게리맨더링 본문
728x90
17471번: 게리맨더링
선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.
www.acmicpc.net
내 풀이
부분집합
public class BOJ_17471 {
static int N;
static int[] people;
static int min;
static ArrayList<ArrayList<Integer>> list;
public static void main(String[] args) throws NumberFormatException, IOException {
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) {
// 선택한거 : isSelected의 true false로 나눠짐
boolean[] visited = new boolean[cnt];
int check = 0;
for (int i = 1; i < cnt; i++) {
if (!visited[i]) {
// 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);
}
}
}
}
728x90
'알고리즘 > 백준' 카테고리의 다른 글
[문제] 백준 15649번 N과 M (1) (0) | 2021.07.13 |
---|---|
[문제] 백준 10844번 쉬운 계단 수 (0) | 2021.04.26 |
[문제] 백준 2636번 치즈 (0) | 2021.03.25 |
[문제] 백준 16236번 아기 상어 (0) | 2021.03.09 |
[문제] 백준 1182번 부분수열의 합 (0) | 2021.03.09 |
Comments