반응형
1. 동전들의 금액 합이 홀수인 경우 절대 둘로 나눌 수 없다.
2. dp(idx, price): [idx...]번 동전들로 price원을 만들 수 있는가
3. dp(idx, price) = max(dp(idx+1, price - coin*cnt)) (0 ≤ cnt ≤ idx번 동전개수)
1. 동전들의 금액 합이 홀수인 경우 절대 둘로 나눌 수 없다.
만약 동전들의 금액 합이 홀수인 경우 절대 둘로 나눌 수 없다. 짝수인 경우에는 sum/2를 만들 수 있는지 확인해보면 된다.
1. dp(idx, price): [idx...]번 동전들로 price원을 만들 수 있는가
dp(idx, price)를 위와 같이 정의하자. 우리가 최종적으로 구하려는 값은 dp(0, sum/2)이다. (이때 sum은 주어진 동전들의 금액 합) 기저사례는 더이상 고려할 동전이 없을 때, 즉 idx = N인 경우가 된다.
2. dp(idx, price) = max(dp(idx+1, price - coin*cnt)) (0 ≤ cnt ≤ idx번 동전개수)
idx번 동전을 0개, 1개, ..., 전부 다 쓰는 경우까지 고려하여 가능한 경우가 있는지 탐색해준다. 이번 동전을 cnt개 쓰는 경우 이제 남은 동전들([idx+1...]번 동전들)로 price - coin*cnt 원을 만들어야 한다.
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
const int MAX_N = 101;
const int MAX_PRICE = 100'001;
int N;
vector<pii> coins;
int cache[MAX_N][MAX_PRICE];
// dp(idx, price): [idx...]번 동전들로 price원을 만들 수 있는가
int dp(int idx, int price) {
if (price < 0) return 0;
if (idx == N) return price == 0;
int& ret = cache[idx][price];
if (ret != -1) return ret;
ret = 0;
for (int i=0; i<=coins[idx].second; i++) {
ret = max(ret, dp(idx+1, price - coins[idx].first*i));
}
return ret;
}
int main() {
for (int t=0; t<3; t++) {
int sum = 0, ans;
cin >> N;
coins.resize(N);
for (int i=0; i<N; i++) {
cin >> coins[i].first >> coins[i].second;
sum += coins[i].first * coins[i].second;
}
if (sum % 2) {
ans = 0;
} else {
memset(cache, -1, sizeof(cache));
ans = dp(0, sum/2);
}
cout << ans << "\n";
}
return 0;
}
반응형
'Problem Solving > BOJ' 카테고리의 다른 글
백준 3584번 가장 가까운 공통 조상 - C++ 풀이 (0) | 2023.08.21 |
---|---|
백준 2224번 명제 증명 - C++ 풀이 (0) | 2023.08.21 |
백준 4179번 불! - C++ 풀이 (0) | 2023.08.10 |
백준 1890번 점프 - C++ 풀이 (0) | 2023.08.09 |
백준 1406번 에디터 - C++ 풀이 (0) | 2023.08.09 |
댓글