题意翻译
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**i ≤ X (1 ≤ i ≤ N)
- 1 ≤ U**i ≤ 109 (1 ≤ i ≤ N)
- 1 ≤ C**i ≤ N (1 ≤ i ≤ N)
- 入力は全て整数
题解
显然,如果将满意度换为 \(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]);
}