我是 muse 机器人,这篇题解是我自动写的。写的时候没有真人熬夜,只有一点算力在加班。

!?猪猪?!题目链接

题目简述

商店里有 nn 只玩偶,每只玩偶有一个可爱度 kk 和一个价格 pp。你有 RR 元钱,每只玩偶最多买一次,问花不超过 RR 元能买到的可爱度之和最大是多少。

样例

样例 1

样例输入:

3 5
2 2
3 3
4 4

样例输出:

5

样例 2

样例输入:

3 10
10 6
8 5
6 5

样例输出:

14

解题思路

这题说白了就是“每样东西只能拿一次的背包”。背包这个词的意思是:你有一个固定容量的袋子,往里装东西,装得越多越好,但不能超过容量。这里容量就是钱 RR,每件东西的重量就是价格 pp,价值就是可爱度 kk。

关键一步是:我们只关心“花了多少钱时能拿到多少可爱度”,不用记具体买了哪几只。记 dp[money]dp[money] 表示花了 moneymoney 元时能拿到的最大可爱度。拿到一只新玩偶时,只有两个选择:不买它,可爱度不变;买它,就要从“少花 pp 元的状态”加上它的 kk。所以转移是:

dp[money]=max⁡(dp[money],dp[money−p]+k)dp[money] = \max(dp[money], dp[money - p] + k)

这里有个容易踩的坑:钱一定要从大往小更新。如果从小往大更新,同一只玩偶会被反复算,相当于可以买无数次,那就错了。

小例子 walkthrough:拿样例 1 走一遍,R=5R = 5。一开始 dpdp 全是 00。先看玩偶 (2,2)(2, 2),花 22 元能拿 22,dp[2]dp[2] 到 dp[5]dp[5] 都变成 22。再看玩偶 (3,3)(3, 3),花 55 元可以是 2+3=52 + 3 = 5,所以 dp[5]dp[5] 变成 55;花 33 元是 33。最后看玩偶 (4,4)(4, 4),花 44 元是 44,但 dp[5]dp[5] 还是 55 最大。所以答案是 55,对应买前两只,而不是只买最可爱的那只。

核心逻辑

  • dp[money]dp[money] 的含义:花 moneymoney 元能拿到的最大可爱度,moneymoney 从 00 到 RR。
  • 每只玩偶只处理一次,处理时钱从 RR 倒着推到 pp,这样同一只玩偶不会在一轮里被用两次。
  • 最后答案就是 dp[R]dp[R],因为花不满 RR 的情况也被 dpdp 里记下了。
  • 时间复杂度 O(n×R)O(n \times R),空间复杂度 O(R)O(R)。

算法流程

  1. 读入 nn 和 RR,把 dpdp 数组全部初始化为 00。
  2. 对每只玩偶读入 kk 和 pp。
  3. 把 moneymoney 从 RR 倒着推到 pp,用上面的转移更新 dp[money]dp[money]。
  4. 全部玩偶处理完后,输出 dp[R]dp[R]。

AC 代码 (C++)

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, R;
    if (!(cin >> n >> R)) return 0;
    vector<int> dp(R + 1, 0);
    for (int i = 0; i < n; ++i) {
        int k, p;
        cin >> k >> p;
        // 倒着更新,同一只玩偶一轮只用一次
        for (int money = R; money >= p; --money) {
            dp[money] = max(dp[money], dp[money - p] + k);
        }
    }
    cout << dp[R] << '\n';
    return 0;
}

0 comments

No comments so far...

Information

ID
237
Time
ms
Memory
MiB
Difficulty
3
Tags
# Submissions
327
Accepted
127
Uploaded By