• 算法:DP, 背包,动态规划

  • 简化版题目:

给定 \(n\) 个物品,物品的价值为 \(v_1 - v_n\),物品的体积为 \(w_1 - w_n\)。需要选择一些物品,使它们的体积和为 \(V\) ,同时让他们的价值和最大。需要注意的是,如果先选择了物品 \(i\) ,后选择了物品 \(j\) (\(i < j\)),那么可以额外获得 \(add_{i, j}\) 的价值。

  • 题目分析:这道题我用的是刷表法(不知道什么是刷表法的请自查)

首先,这道题明显是一道 01背包 吧(

但是这道题和普通01背包不一样的地方是,当我们选择当前物品是,还需要考虑下一个要选择的是什么物品(因为有可能额外增加价值嘛...毕竟还是想多赚一点)。

所以,我们在 01 背包的 dp 数组基础上多开一维,用来记录当前在选择第几个物品。这样,我们在转移的时候,用 for 循环枚举的时候,就可以清楚的查询到上次使用的魔法是什么了。

设当前要选择第 \(i\) 个魔法,接下来要选的是第 \(j\) 个魔法,在选择 \(i\) 的时候已经用掉了 \(k\) 的背包容积。

转移方程为: \(f_{j, k + w_j} = max(f_{j, k + w_j}, f_{i, k} + v_j + add_{i, j})\)。

代码大概长这个样子(注意这是错误代码 ...)

   memset(f, -0x3f, sizeof f);
f[0][0] = 0; for (int i = 0; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ )
for (int k = m; k >= 0; k -- )
f[j][k + w[j]] = max(f[j][k + w[j]], f[i][k] + v[j] + add[i][j]);

恭喜你拿到了 50 pts

为什么呢?不知道你有没有注意到题目的数据范围的绝对值符号...难道魔法咒语的长度还能为负数(对于这点我是真的雾

所以,我们需要在 \(f\) 数组上面加上一个偏移量 \(delta\) (因为数组下标不能为负数嘛)

对于无解输出 -1 的情况,特判掉就可以了。如果每个咒语魔法值都是负的,增加的魔法值 \(add\) 也都取成最小,那么答案最劣就是 ($ -50-50$) \(\times \ 50 = -5000\),也就是说,如果我们的结果小于 -5000,那么可以直接判定为 -1 。

  • 参考代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm> using namespace std; const int N = 52, M = 2500; int v[N], w[N];
int f[N][(M << 1) + 10];
int n, m, add[N][N];
int delta = 2500; int main()
{
scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++ )
scanf("%d%d", &w[i], &v[i]); for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
scanf("%d", &add[i][j]); memset(f, -0x3f, sizeof f);
f[0][delta] = 0; for (int i = 0; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ )
for (int k = delta << 1; k >= 0; k -- )
f[j][k + w[j]] = max(f[j][k + w[j]], f[i][k] + v[j] + add[i][j]); int res = -0x3f3f3f3f; for (int i = 1; i <= n; i ++ )
res = max(res, f[i][m + delta]); printf("%d\n", (res < -5000 ? -1 : res)); return 0;
}

这样就轻松拿到 rk1

再贴一个拿到 rk2 的填表法代码叭(就当免费赠送了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm> using namespace std; const int N = 60, M = 2510;
int f[N][M << 1]; // f[i][j] 表示选择第 i 个物品,体积为 v 的价值。
int n, m;
int v[N], w[N], add[N][N];
int delta = 2500; int main()
{
scanf("%d%d", &n, &m); // n 为物品数量,m 为背包容积 for (int i = 1; i <= n; i ++ )
scanf("%d%d", &v[i], &w[i]); for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
scanf("%d", &add[i][j]); memset(f, -0x3f, sizeof f);
f[0][delta] = 0; for (int i = 1; i <= n; i ++ ) // 枚举当前要用什么魔法
for (int j = delta + delta; j >= v[i]; j -- ) // 枚举当前剩余咒语长度(容积)
for (int k = 0; k < i; k ++ ) // 枚举上一个使用的是什么魔法
f[i][j] = max(f[i][j], f[k][j - v[i]] + w[i] + add[k][i]); int res = -0x3f3f3f3f;
for (int i = 1; i <= n; i ++ )
res = max(res, f[i][m + delta]); printf("%d\n", (res < -5000) ? -1 : res); return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

[Luogu 4912 帕秋莉的魔法] 题解报告的更多相关文章

  1. [Luogu] P4910 帕秋莉的手环

    题目背景 帕秋莉是蕾米莉亚很早结识的朋友,现在住在红魔馆地下的大图书馆里.不仅擅长许多魔法,还每天都会开发出新的魔法.只是身体比较弱,因为哮喘,会在咏唱符卡时遇到麻烦. 她所用的属性魔法,主要是生命和 ...

  2. 【题解】Luogu P4910 帕秋莉的手环

    原题传送门 "连续的两个中至少有1个金的"珂以理解为"不能有两个木相连" 我们考虑一个一个将元素加入手环 设f\([i][0/1]\)表示长度为\(i\)手环末 ...

  3. P4910 帕秋莉的手环

    题目背景 帕秋莉是蕾米莉亚很早结识的朋友,现在住在红魔馆地下的大图书馆里.不仅擅长许多魔法,还每天都会开发出新的魔法.只是身体比较弱,因为哮喘,会在咏唱符卡时遇到麻烦. 她所用的属性魔法,主要是生命和 ...

  4. 【Cogs2187】帕秋莉的超级多项式(多项式运算)

    [Cogs2187]帕秋莉的超级多项式(多项式运算) 题面 Cogs 题解 多项式运算模板题 只提供代码了.. #include<iostream> #include<cstdio& ...

  5. cogs 998. [東方S2] 帕秋莉·诺蕾姬

    二次联通门 : cogs 998. [東方S2] 帕秋莉·诺蕾姬 交上去后发现自己没上榜 就想着加点黑科技 把循环展开一下 结果WA了.. 万恶的姆Q /* cogs 998. [東方S2] 帕秋莉· ...

  6. P4915 帕秋莉的魔导书(动态开点线段树)

    题目背景 帕秋莉有一个巨大的图书馆,里面有数以万计的书,其中大部分为魔导书. 题目描述 魔导书是一种需要钥匙才能看得懂的书,然而只有和书写者同等或更高熟练度的人才能看得见钥匙.因此,每本魔导书都有它自 ...

  7. 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解

    矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...

  8. [洛谷P4910]帕秋莉的手环

    题目大意:有一个$n(n\leqslant10^{18})$个点的环,每个点可以是$0$或$1$,要求相邻点中至少一个$1$,问方案数,多组询问. 题解:先考虑是一条链的情况,令$f_{i,j}$表示 ...

  9. COGS2187 [HZOI 2015] 帕秋莉的超级多项式

    什么都别说了,咱心态已经炸了... question 题目戳这里的说... 其实就是叫你求下面这个式子的导函数: noteskey 其实是道板子题呢~ 刚好给我们弄个多项式合集的说... 各种板子粘贴 ...

  10. COGS 2189 帕秋莉的超级多项式

    放模板啦! 以后打比赛的时候直接复制过来. 说句实话vector的效率真的不怎么样,但是似乎也还行,最主要是……写得比较爽. #include <cstdio> #include < ...

随机推荐

  1. Java新特性中的Preview功能如何运行和调试

    在每个Java新版本发布的特性中,都会包含一些Preview(预览)功能,这些功能主要用来给开发者体验并收集建议.所以,Preview阶段的功能并不是默认开启的. 如果想体验某个Java版本中的Pre ...

  2. Android利用广播监听按下HOME和电源键

    package cc.testhome; import cc.testhome.HomeKeyObserver.OnHomeKeyListener; import cc.testhome.PowerK ...

  3. K8s部署轻量级日志收集系统EFK(elasticsear + filebeat + kibana)

    目录 K8s部署EFK(elasticsear + filebeat + kibana)日志收集 一.准备镜像 二.搭建Elasticsearch + kibana 1.在可执行kubectl命令的服 ...

  4. 【前端小技巧】如何使用 Eolink Apilkit 调用 Mock ?

    在开发过程中,进度比较赶的情况下,前端人员当页面写完时,后台的接口还没写完,等要交付的时候后端才把接口给你,这个时候就很尴尬. 这个时候 Mock 就可以很好的解决这个问题,前端团队可以在 API 还 ...

  5. 传纸条 luoguP1006

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排坐成一个 mm 行 nn 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈 ...

  6. CSP初赛错题集

    初赛错题集 洛谷有题 NOIP 2018 T9 给定一个含N 个不相同数字的数组,在最坏情况下,找出其中最大或最小的数,至少需要N - 1 次比较操作.则最坏情况下,在该数组中同时找最大与最小的数至少 ...

  7. LVS+keepalived结合

    LVS+Keepalived实现高可用负载均衡(web集群) LVS+Keepalived架构图:   测试环境: 名称 操作系统 IP地址 LVS-MASTER Centos7.x 192.168. ...

  8. 9.11 多校联测 Day1 总结

    我的想法是,你如果没读过题,看了这篇总结完全不能知道题面是啥,不存在泄题风险.所以不设密码力() 状态极差. 昨晚忘记定闹钟,好在早上突然想起今天考试惊醒了,rp--. 不过没有提前一个小时起来导致考 ...

  9. keycloak~为keycloak-services项目添加第三方模块(首创)

    我们在对keycloak框架中的核心项目keycloak-services进行二次开发过程中,发现了一个问题,当时有这种需求,在keycloak-services中需要使用infinispan缓存,我 ...

  10. 2021CSP 游记

    总结 试机日: 我天,这学校什么垃圾电脑-- 比赛日: 1. 普及考试 总体上来说题目算简单 (只是我脑残),t1简单 \(O(1)\),学了数论就行,而 t2 看懂后按题意打一遍,再优化一下: 数组 ...