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 | 29 | 30 | 31 |
Tags
- Eulerian circuit
- graph
- dynamic programming
- GCD
- Algospot
- mathematics
- disjoint-set
- Euler path
- BOJ
- flows
- Greedy
- bitmask
- hashing
- Sieve_of_Eratosthenes
- BST
- 백준
- scc
- graph modeling
- CS Academy
- Eulerian path
- Segment Tree
- backtracking
- Cycle detecting
- POJ
- DynamicProgramming
- BFSDFS
- Dag
- Euler circuit
- implementation
- Shortest path
Archives
- Today
- Total
그냥 하는 노트와 메모장
BOJ 1226 국회 본문
BOJ 1226 국회
[분류 - 다이나믹 프로그래밍, 그리디]
[풀이] 당을 하나씩 추가하면서 전체의 절반을 초과하는 경우를 봐야한다.
$$a_i=의석수$$
$$total=\sum_{i=1}^{n} a_i$$
$$ half=\lfloor{total/2}\rfloor $$
[접근] 0부터 half까지 순회하면서 현재 좌석수를 더해줌으로 절반을 초과하는지 확인하면된다.
[그리디] 단, 좌석수 기준 비오름차순으로 정렬한 데이터를 가지고 추가해야한다. 조건에서 보면 현재 좌석 수를 x로 구성했을 때 x를 만들기 위해 연합된 당들 각각 하나를 빼면 좌석수가 절반 이하이어야만 한다. 현재 당의 좌석수가 ci라고 할때 현재 당을 제외한 나머지 당으로 half를 구성했다고 치자. 그러면 half + ci도 정답 후보가 될 수 있을텐데, 구성된 당 중 하나를 빼면 반드시 절반 이하가 되기 위해서는 half로 구성한 당 모두가 반드시 ci보다 크거나 같아야만 조건을 만족시킬 수 있다.
[다이나믹] 나머지 부분은 다이나믹 부분으로 정렬된 당에 대해 half부터 0까지 순회하면서 어느 부분에서 최대가 될 수 있는지, 어느 당을 사용했는지를 같이 저장해서 나중에 최대값 좌석수에 대해 거꾸로 추적해나가면 된다.
(참고) 다이나믹 부분은 주어진 동전으로 화폐를 구성하는 경우의 수를 구하는 문제와 매우 흡사하다
더보기
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 301, MAX_S = 1e5 + 1, HEAD = 1e9;
int main() {
int N, trace[MAX_S] = { HEAD }, i, j, tot = 0, half, maxi = -1, C[MAX_N];
pair<int, int> c[MAX_N];
vector<int> ans;
scanf("%d", &N);
for (i = 1; i <= N; i++) {
scanf("%d", &C[i]);
c[i].first = C[i];
c[i].second = i;
tot += c[i].first;
}
c[0].second = HEAD;
sort(c + 1, c + N + 1);
half = tot / 2;
for (i = N; i >= 1; i--) {
for (j = half; j >= 0; j--) if (trace[j] && !trace[j + c[i].first]) {
trace[j + c[i].first] = c[i].second;
if (maxi < j + c[i].first)
maxi = j + c[i].first;
}
}
while (1) {
i = trace[maxi];
if (i == HEAD)
break;
maxi -= C[i];
ans.push_back(i);
}
printf("%d\n", ans.size());
for (int& a : ans) printf("%d ", a);
return 0;
}
'Solved problems' 카테고리의 다른 글
BOJ 1600 - 말이 되고픈 원숭이 (0) | 2020.11.13 |
---|---|
BOJ 8902 색상의 길이 (0) | 2020.07.01 |
BOJ 1128 피보나치 냅색 (0) | 2020.06.22 |
BOJ 18892 가장 긴 증가하는 부분 수열 ks (0) | 2020.06.19 |
BOJ 3217 malloc (0) | 2020.06.19 |
Comments