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

posted @ 2024-12-13 16:30  onlyblues  阅读(28)  评论(0)    收藏  举报
Web Analytics