Loading [MathJax]/jax/output/HTML-CSS/jax.js

백준 5550번 (JOI 2011년 2번), 헌책방 풀이

2020. 9. 27. 11:29Problem Solving/백준

문제

백준 5550번

풀이

전형적인 DP (누적합+그리디) 문제로 볼 수 있습니다.

 

"dp[i] = i권을 선택했을 때 만들 수 있는 최대 가격" 으로 점화식을 세워줍시다.

 

모든 장르에 대해서 i번째 책까지 골랐을 때, 해당 장르의 j개의 책을 추가로 고르는 경우로 DP table을 채워주면 됩니다.

 

시간복잡도는 O(GN2)이 되는데, N이 1000이고 G가 10이므로 G는 무시할만한 수준입니다.

따라서, DP의 시간복잡도는 O(N2)이 됩니다.

 

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];
}