F - Diversity
F - Diversity
Problem Statement
There are $N$ products for sale in a store. The $i$-th product has a price of $P_i$ yen, a utility value of $U_i$, and a color $C_i$.
You will choose some subset of these $N$ products to buy (possibly none). The total price of the chosen products must be at most $X$ yen.
Your satisfaction is $S + T \times K$, where $S$ is the sum of utilities of the chosen products, and $T$ is the number of distinct colors among the chosen products. Here, $K$ is a given constant.
You will choose products to maximize your satisfaction. Find the maximized satisfaction.
Constraints
- $1 \leq N \leq 500$
- $1 \leq X \leq 50000$
- $1 \leq K \leq 10^9$
- $1 \leq P_i \leq X$ $(1 \leq i \leq N)$
- $1 \leq U_i \leq 10^9$ $(1 \leq i \leq N)$
- $1 \leq C_i \leq N$ $(1 \leq i \leq N)$
- All input values are integers.
Input
The input is given from Standard Input in the following format:
$N$ $X$ $K$
$P_1$ $U_1$ $C_1$
$P_2$ $U_2$ $C_2$
$\vdots$
$P_N$ $U_N$ $C_N$
Output
Print the answer.
Sample Input 1
3 10 5
1 3 1
7 4 2
4 5 1
Sample Output 1
17
If you buy the 1st and 2nd products, the total utility $S$ is $7$, and the number of distinct colors $T$ is $2$. Thus, your satisfaction is $7 + 2 \times 5 = 17$. No purchase plan makes your satisfaction $18$ or greater, so the answer is $17$.
Sample Input 2
5 30 3
5 4 3
11 20 1
9 10 4
7 5 2
16 15 4
Sample Output 2
44
If you buy the 2nd, 3rd, and 4th products, the total utility $S$ is $35$, and the number of distinct colors $T$ is $3$. Thus, your satisfaction is $35 + 3 \times 3 = 44$. No purchase plan makes your satisfaction $45$ or greater, so the answer is $44$.
Sample Input 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
Sample Output 3
67717
解题思路
还是挺容易想到按照颜色分组然后 dp,定义 $f(i,j)$ 表示从前 $i$ 种颜色的物品中选出总价格不超过 $j$ 的所有方案中能获得的最大价值。
不过赛时不知道怎么转移,就对每个分组求一次 01 背包。定义 $g_i(j,k)$ 表示从颜色为 $i$ 的前 $j$ 个物品中选出总价格不超过 $k$ 的所有方案中能获得的最大价值。这样 $f(i,j)$ 就能通过 $g(s_i, k)$ 进行转移($s_i$ 表示颜色 $i$ 的物品数量),转移方程就是 $f(i,j) = \max\left\{ f(i-1,j), \, \max\limits_{1 \leq k \leq j}\left\{ f(i-1, j - k) + g(s_i, k) \right\} + K \right\}$,显然整个 dp 的复杂度是 $O(nm^2)$ 会超时。
事实上并没有那么麻烦,不过题解给出的转移方法我就是想不到。为了更好的描述,这里重新定义状态 $f(i,j,k)$ 表示从前 $i-1$ 种颜色以及第 $i$ 种颜色的前 $j$ 个中的物品中选出总价格不超过 $k$ 的所有方案中能获得的最大价值。根据第 $i$ 种颜色的第 $j$ 个物品是否选择以及是否为首次选择该颜色物品进行状态划分,状态转移方程就是 $f(i,j,k) = \max\left\{ f(i,j-1,k), \, f(i-1,s_{i-1},k-v_j) + w_j + K, \, f(i,j-1,k-v_j) + w_j \right\}$。
其实这个有点类似于分组背包问题,不过不同的地方在与本问题中每个分组的物品可以任意选择。另外题解中把上述状态的第二维优化掉了,需要注意的是优化后要从大到小枚举价格 $k$ 来转移,以避免与 01 背包类似的问题。
AC 代码如下,时间复杂度为 $O(nm)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 505, M = 50005;
vector<array<int, 2>> g[N];
LL f[N][M];
int main() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 0; i < n; i++) {
int v, w, c;
cin >> v >> w >> c;
g[c].push_back({v, w});
}
for (int i = 1; i <= n; i++) {
memcpy(f[i], f[i - 1], m + 1 << 3);
for (auto &[v, w] : g[i]) {
for (int j = m; j >= v; j--) {
f[i][j] = max(f[i][j], f[i - 1][j - v] + w + k);
f[i][j] = max(f[i][j], f[i][j - v] + w);
}
}
}
cout << f[n][m];
return 0;
}
参考资料
Editorial - Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383):https://atcoder.jp/contests/abc383/editorial/11543
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18605240

浙公网安备 33010602011771号