Aizu Online Judge 0561 - Books

解法

動的計画法です.
あるジャンルiにおいて, 本をx冊選ぶとします. このとき最も高額で売るためには金額が最も高い方からx冊選ぶことが最適です. あとはジャンルと選んだ本の冊数でナップザックです.

ソースコード

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> ci[10];
vector<int> items[10];
int dp[11][2020];
  
int main() {
    int N, K;
    cin >> N >> K;

    for (int i = 0; i < N; i++) {
        int c, g;
        cin >> c >> g;
        ci[g - 1].push_back(c);
    }

    for (int i = 0; i < 10; i++) {
        sort(ci[i].begin(), ci[i].end(), greater<int>());

        items[i] = vector<int>(ci[i].size());
        for (int j = 0; j < ci[i].size(); j++) {
            int sum = 0;
            for (int k = 0; k <= j; k++) {
                sum += ci[i][k];
            }
            items[i][j] = sum + j * (j + 1);
        }
    }

    for (int i = 0; i < 10; i++) {
        for (int j = 0; j <= K; j++) {
            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
            for (int k = 0; k < items[i].size(); k++) {
                if (j + k + 1 <= K) {
                    dp[i + 1][j + k + 1] = max(dp[i + 1][j + k + 1], dp[i][j] + items[i][k]);
                }
            }
        }
    }
    cout << dp[10][K] << endl;

    return 0;
}

感想

TLE本の練習問題です. DPは解けると楽しいですね.