题意翻译

Aya 非常喜欢奶龙。

今天他来到商店,发现商店里正在出售 N 个奶龙!第 i 个奶龙的价格是 \(p_i\) 元,实用性是 \(u_i\),颜色是 \(c_i\)

Aya 可以选择所有奶龙的一个子集进行购买(可以是空集),但最多只能用 X 元。

Aya 的满意度是 S+T×K,其中 S 是购买的奶龙实用性之和,T 是购买的奶龙中不同颜色的种类数,K 是一个给定的常数。

请帮 Aya 最大化满意度。

Translated by @SSqwq_

输入输出样例

输入 #1复制

3 10 5
1 3 1
7 4 2
4 5 1

输出 #1复制

17

输入 #2复制

5 30 3
5 4 3
11 20 1
9 10 4
7 5 2
16 15 4

输出 #2复制

44

输入 #3复制

22 75 6426
9 309 9
5 470 5
17 481 12
27 352 14
1 191 18
7 353 20
9 99 15
20 401 17
46 434 19
11 459 22
10 317 19
15 440 18
17 438 19
25 461 22
5 320 22
1 476 21
11 315 3
8 112 9
11 438 13
19 362 8
10 422 13
10 152 21

输出 #3复制

67717

说明/提示

制約

  • 1 ≤ N ≤ 500
  • 1 ≤ X ≤ 50000
  • 1 ≤ K ≤ 109
  • 1 ≤ P**iX (1 ≤ iN)
  • 1 ≤ U**i ≤ 109 (1 ≤ iN)
  • 1 ≤ C**iN (1 ≤ iN)
  • 入力は全て整数

题解

显然,如果将满意度换为 \(S\) ,此题就是一个经典的背包dp问题。
在经典背包dp问题中,\(f[i][j]\) 表示为前 \(i\) 个物品在 \(j\) 元限制下的满意度 \(S\)。但由于该题目的满意度为 \(S+T \times K\),在不进行排序的情况下,\(f[i]\) 的情况要受到之前选择的颜色情况,不满足无后效性,故不能使用\(f[i][j]\) 表示为前 \(i\) 个物品在 \(j\) 元限制下的满意度。
现在考虑如何解决颜色的后效性问题,容易想到当对颜色进行分组排序,将颜色序号视为\(i\),即 \(f[i][j]\) 为选择前 \(i\) 种颜色的物品在 \(j\) 元限制下的满意度,共有三个状态。

\[f[i][j] = max\{f[i][j],f[i-1][j-p]+u+k,f[i][j-p]+u,f[i-1][j]\} \]

#include<iostream>
#include<vector>
#include<utility>
#include<cstring>
#define INF 1e9
#define inf -1e9
using namespace std;

int n, x, k;
vector<PII> E[510];
int f[510][5010];

int main() {
	cin >> n >> x >> k;
	int p, u, c;
	for (int i = 1; i <= n; i++) {
		cin >> p >> u >> c;
    	E[c].push_back({p, u});
    }
    memset(f, inf, sizeof(f));
    f[0][0] = 0;
    for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= x; j++) f[i][j] = max(f[i][j], f[i - 1][j]);//不选择第i种颜色
        for (auto &[p, u]:E[i]) {//选择第i种颜色的状态
            for (int j = x; j >= p; j--){
            	f[i][j] = max(f[i - 1][j - p] + u + k, f[i][j]);//未选择第i种颜色
            	f[i][j] = max(f[i][j - p] + u, f[i][j]);//已经选择过第i种颜色
        	}
        }
        
    }
    int ans = 0;
    for (int i = 1; i <= x; i++) ans = max(ans, f[n][i]); 
}