일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 특수목적기구
- 매일경제
- 웅덩이 매매법
- 자의식 해체
- 경제기사 읽기
- 제로금리정책
- 유전자오작동
- 부동산기사읽기
- 엥겔의법칙
- 자발적 실업
- 평균급여액
- 경제금융용어
- 구해줘월부
- 역행자
- 정체성 만들기
- 원금리스크
- 경제적 자유를 위한 5가지 공부법
- 업무지구별
- 연방준비제도(FRS)/연방준비은행(FRB)
- 한국직업개발원
- 경제 기사읽기
- 황농문 서울대교수
- 백준 1238
- 부동산 기사읽기
- 백준 파티
- KFO
- 이중통화채(dual currency bond)
- 월부TV
- 행크TV
- 급여액
- Today
- Total
록키의 No Pain, No Gain
[BOJ] 17471번 게리멘더링 본문
https://www.acmicpc.net/problem/17471
17471번: 게리맨더링
선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.
www.acmicpc.net
문제
1번부터 N번까지 번호가 매겨진 N개의 구역이 있다. 구역을 두 개의 선거구로 나누고, 각 구역은 두 선거구 중 하나에 포함되어야 한다. 선거구는 구역을 적어도 하나 포함해야 하고, 한 선거구에 포함되어 있는 구역은 모두 연결되어 있어야 한다. 공평하게 선거구를 나누기 위해 두 선거구에 포함된 인구의 차이를 최소로 하려고 한다. 인구 차이의 최솟값을 구해보자
풀이
비트마스킹을 이용한 부분집합 + BFS를 이용하여 풀었다.
일단 구역을 A선거구, B선거구로 나누고 1번 구역은 무조건 A선거구에 들어가도록 설정했다. 왜냐하면 A 선거구에 1,2,3번 구역이 들어가고 B선거구에 4,5,6번 구역이 들어가는 것이랑 A선거구에 4,5,6번 구역이 들어가고 B구역에 1,2,3번 구역이 들어가는 것은 같은 경우이기 때문이다.
그리고 비트 마스크를 이용해서 1 ~ (1 << N-1) - 1에 대해서 각 자리의 비트가 1인경우 B선거구에 넣고 0인 경우 A선거구에 넣었다. 예를 들어 01001인 경우 첫번째와 네번째 비트가 1이고, 나머지 비트가 0이다. 이 때 이미 1번 구역은 A선거구에 넣었기 떄문에 제외하면, 2번 구역이 첫번째 비트를 맡게 되고 3번 구역이 두 번째 비트 .. 뭐 이런식으로 된다.
따라서 이 경우 2번, 5번 구역을 A선거구에 나머지 비트가 0인 구역은 B선거구에 넣었다.
이렇게 두 선거구로 나눈 다음에 BFS로 문제를 풀었다.
실수 했던 부분
처음에 입력 받을때 vector에 push_back해주는 것을 뺴먹었다.
그리고 BFS과정에서 q.push()와 visited 배열 변경은 짝꿍처럼 같이 다니는 것인데 이걸 빼먹었다.. 뭐 큰 실수는 아니지만...
/*
제한사항
1. 구역을 두 개의 선거구, 각 구역은 두 선거구 중 하나에 포함되어야..
2. 선거구는 구역을 적어도 하나 포함해야 함
3. 한 선거구에 포함된 구역은 모두 연결 되어야 한다.
4. 인접한 구역이 없을 수도 있다.
5. 두 선거구로 나눌 수 없는 경우에는 -1을 출력한다.
구해야 하는 것
두 선거구의 인구 차이의 최솟값
*/
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int N, answer;
int p[11];
bool visited[11];
vector<vector<int>> adj;
vector<int> teamA;
vector<int> teamB;
void init() {
for (int i = 1; i <= N; i++) visited[i] = false;
}
void BFS() {
int Acnt = teamA.size();
int Bcnt = teamB.size();
int Asum = 0;
int Bsum = 0;
queue<int> q;
//먼저 teamA부터 BFS
q.push(teamA[0]);
visited[teamA[0]] = true;
Acnt--;
Asum += p[teamA[0]];
if (Acnt != 0) {
while (!q.empty()) {
int curr = q.front();
q.pop();
//curr에 인접한 노드 중에서
for (int i = 0; i < adj[curr].size(); i++) {
int next = adj[curr][i];
for (int j = 1; j < teamA.size(); j++) {
if (teamA[j] == next && !visited[next]) {
q.push(next);
visited[next] = true;
Acnt--;
Asum += p[next];
break;
}
}
if (Acnt == 0) {
break;
}
}
if (Acnt == 0) break;
}
}
if (Acnt != 0) return;
//그리고 teamB BFS
while (!q.empty()) q.pop();
q.push(teamB[0]);
visited[teamB[0]] = true;
Bcnt--;
Bsum += p[teamB[0]];
if (Bcnt != 0) {
while (!q.empty()) {
int curr = q.front();
q.pop();
for (int i = 0; i < adj[curr].size(); i++) {
int next = adj[curr][i];
for (int j = 1; j < teamB.size(); j++) {
if (teamB[j] == next && !visited[next]) {
q.push(next);
visited[next] = true;
Bcnt--;
Bsum += p[next];
break;
}
}
if (Bcnt == 0) {
break;
}
}
if (Bcnt == 0) break;
}
}
if (Bcnt != 0) return;
answer = min(answer, abs(Asum - Bsum));
}
int main() {
//무조건 초기화 하는 것은 입력 전에 하기
answer = 100 * 10 + 1;
cin >> N;
for (int i = 1; i <= N; i++) cin >> p[i];
vector<int> a;
adj.push_back(a);
int cnt, adjNode;
for (int i = 1; i <= N; i++) {
cin >> cnt;
vector<int> tmp;
for (int j = 1; j <= cnt; j++) {
cin >> adjNode;
tmp.push_back(adjNode);
}
//밑에 push_back 부분에 대한 실수가 있었다.
adj.push_back(tmp);
}
//잘 한 부분 팀을 두개로 나누고 출력값을 확인해봤음.
for (int i = 1; i < (1 << (N - 1)); i++) {
teamA.clear(); teamB.clear();
teamA.push_back(1);
for (int j = 0; j < N - 1; j++) {
//비트가 1이면 B팀에 넣어줌
if (i & (1 << j)) {
teamB.push_back(j + 2);
}
//비트가 0이면 A팀에 넣어줌
else {
teamA.push_back(j + 2);
}
}
//잘 한 부분 BFS전에 visited 배열 초기화 해주는 습관
init();
BFS();
}
if (answer == 100 * 10 + 1) cout << -1;
else cout << answer;
}
'알고리즘' 카테고리의 다른 글
[BOJ] 16235번 나무 재테크 (0) | 2020.05.21 |
---|---|
[SWEA] 점심 식사시간 (0) | 2020.05.13 |
[BOJ] 17822번 원판 돌리기 (0) | 2020.04.28 |
[BOJ] 17825 주사위 윷놀이 (0) | 2020.04.28 |
[BOJ] 17142번 연구소 3 (0) | 2020.04.26 |