惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
IT之家
IT之家
博客园_首页
博客园 - 【当耐特】
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
GbyAI
GbyAI
腾讯CDC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
H
Help Net Security
T
Tailwind CSS Blog
B
Blog RSS Feed
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
博客园 - 叶小钗
雷峰网
雷峰网
量子位

distjr_的博客

最新 | Galgame Maker 运行时引擎 README 最新 | 关于我的高中三年 | distjr_的博客 欸嘿 | distjr_的博客 最新 | 画中少女 | distjr_的博客 天津行记 | distjr_的博客 最终选择去天津大学了 | distjr_的博客 上伊那牡丹,看完了 | distjr_的博客 上伊那牡丹,看完了 | distjr_的博客 帖子测试 | distjr_的博客 最新 | 关于我的高中三年 | distjr_的博客 最新 | KeepOpen:一款保持移动硬盘开启状态的小工具 | distjr_的博客 最新 | KeepOpen:一款保持移动硬盘开启状态的小工具 | distjr_的博客 最新 | 关于我的高中三年 | distjr_的博客 一款基于Python的随机学生点名器 | distjr_的博客 最新 | 一款基于Python的随机学生点名器 | distjr_的博客 U571839 千本桜 题解 | distjr_的博客 U571839 千本桜 题解 | distjr_的博客 巴别塔 | distjr_的博客 土地 | distjr_的博客 土地 | distjr_的博客 一九六八年 | distjr_的博客 一九六八年 | distjr_的博客 原野 | distjr_的博客 原野 | distjr_的博客 一种基于人工智能技术的系统发生树绘制与物种演化路径推断系统 | distjr_的博客 一种基于人工智能技术的系统发生树绘制与物种演化路径推断系统 | distjr_的博客 回来?Ⅱ | distjr_的博客 回来?Ⅱ | distjr_的博客 U314392 distjr_想买书 题解 | distjr_的博客 天涯边 | distjr_的博客
U314392 distjr_想买书 题解 | distjr_的博客
文章作者: distjr_ · 2024-02-18 · via distjr_的博客

思路

首先是一个 dp 的板子,设 $dp_j$ 为花费 $j$ 元能获得的最大的期待值。

对于每次转移,都可以选择买哪一本书,一旦买了一本书,花费的钱增加 $p_i$ ,获得的总期待值增加 $v_i$ 。

故不难看出状态转移方程为 $dp_j = \max \lbrace dp_{j-p_i}+v_i \rbrace $。

但题目还要求输出方案,所以开一个 vector 记录方案,每次找到更优的方案时,就在上一个方案的后面补上当前新增加的物品,由于输入是单调的,自然保证输出是单调的。

同时,还要设置一个标记数组 flag 以筛去不合法的答案,确保所有找到的方案都是正常计算得来的,否则可能会出现一些奇奇怪怪的bug。

感谢 linmou 提供的 std!

std

/**
 * @file buy.cpp
 * @brief Solution of Luogu U314392
 * @date 2024-02-18
 */
#include <cstdio>
#include <vector>
#define MAXN 505
#define MAXM 500005
using namespace std;

int n, m, a, maxx = 0, v[MAXM], p[MAXM], dp[MAXM], ans;
bool flag[MAXN][MAXM];
vector<int> programme;

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d %d %d", &a, &p[i], &v[i]);
    flag[n + 1][0] = 1;
    for (int i = n; i >= 1; i--)
    {
        for (int j = 0; j <= m; j++)
            flag[i][j] = flag[i + 1][j];
        for (int j = m; j >= p[i]; j--)
        {
            if (!flag[i + 1][j - p[i]])
                continue;
            if (dp[j] <= v[i] + dp[j - p[i]]) // 状态转移
            {
                dp[j] = v[i] + dp[j - p[i]];
                flag[i][j] = flag[i][j] | flag[i + 1][j - p[i]]; // 标记
            }
        }
    }
    for (int i = 1; i <= m; i++) // 选出最优方案
        if (maxx <= dp[i])
            maxx = dp[i], ans = i;
    int i = 1, j = ans, sum = 0;
    while (i <= n && j)
    {
        if (flag[i][j] && flag[i][j - p[i]])
        {
            printf("%d ", i);
            sum += p[i];
            j -= p[i];
        }
        i++;
    }
    return 0;
}