백준 5550번 (JOI 2011년 2번), 헌책방 풀이
2020. 9. 27. 11:29ㆍProblem Solving/백준
문제
풀이
전형적인 DP (누적합+그리디) 문제로 볼 수 있습니다.
"dp[i] = i권을 선택했을 때 만들 수 있는 최대 가격" 으로 점화식을 세워줍시다.
모든 장르에 대해서 i번째 책까지 골랐을 때, 해당 장르의 j개의 책을 추가로 고르는 경우로 DP table을 채워주면 됩니다.
시간복잡도는 $ O(GN^2) $이 되는데, N이 1000이고 G가 10이므로 G는 무시할만한 수준입니다.
따라서, DP의 시간복잡도는 $ O(N^2) $이 됩니다.
DP의 조건이 좀 까다로워 구현하는데 고생했던 것 같습니다.
소스코드
#include <bits/stdc++.h>
using namespace std;
int dp[2001];
vector<int> book[11], sum[11];
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++) {
int a, b;
cin >> a >> b;
book[b].push_back(a);
}
for (auto &vec : book) sort(vec.begin(), vec.end(), greater<>());
for (int i = 1; i <= 10; i++) {
auto vec = book[i];
sum[i].resize(vec.size());
for (int j = 0; j < vec.size(); j++) {
sum[i][j] = (j ? sum[i][j - 1] : 0) + vec[j];
}
}
for (const auto &books : sum)
for (int base_cnt = k; base_cnt >= 0; base_cnt--)
for (int j = 1; j <= books.size(); j++) {
if (base_cnt + j > k) break;
if (!base_cnt || dp[base_cnt])
dp[base_cnt + j] = max(dp[base_cnt + j], dp[base_cnt] + books[j - 1] + (j - 1) * j);
}
cout << dp[k];
}
'Problem Solving > 백준' 카테고리의 다른 글
백준 14462, 소가 길을 건너간 이유 8 (0) | 2020.09.29 |
---|---|
백준 1806번, 부분합 풀이 (0) | 2020.09.28 |
백준 12930번, 두 가중치 풀이 (0) | 2020.09.27 |
백준 1197번, 최소 스패닝 트리(MST)를 구하는 크루스칼 알고리즘 (0) | 2020.09.27 |
백준 8983번, 한국정보올림피아드(KOI) 2013 고등부 1번, 사냥꾼 풀이 (0) | 2020.09.27 |