• 算法: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. WebApi中添加Jwt鉴权

    前言 JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息.一个 JWT 实际上就是一个字符串,它由三部分组成,头部.载荷与签 ...

  2. Dubbo3应用开发—Dubbo服务管理平台DubboAdmin介绍、安装、测试

    Dubbo服务管理平台 DubboAdmin的介绍 Dubbo Admin是Apache Dubbo服务治理和管理系统的一部分. Dubbo Admin提供了一套用于服务治理的Web界面,让我们可以更 ...

  3. Go 基础之基本数据类型

    Go 基础之基本数据类型 目录 Go 基础之基本数据类型 一.整型 1.1 平台无关整型 1.1.1 基本概念 1.1.2 分类 有符号整型(int8~int64) 无符号整型(uint8~uint6 ...

  4. jdk-14.0.1环境搭建及cmd环境编译执行

    1.安装包获取 https://www.oracle.com/java/technologies/javase/jdk14-archive-downloads.html 2.环境变量配置 最新版本的J ...

  5. python第6章 学习笔记

    # 第6章 学习笔记## 简介 Python代码在执行时是按照自上向下顺序执行的. 通过流程控制语句,可以改变程序的执行顺序,也可以让指定的程序反复执行多次 流程控制语句分成两大类:条件判断语句,循环 ...

  6. qq群匿名聊怎么用

    qq群匿名聊怎么用 1 2 3 4 5 分步阅读 匿名的意思就是不认识.群匿名聊当然是把群里的马甲一下变成不认识的人,再在一起聊天.是不是觉得有点吃饱了没事干,但是当下该功能还是比较实用的,群匿名聊可 ...

  7. nginx中一个请求匹配到多个location时的优先级问题,马失前蹄了

    背景 为什么讲这么小的一个问题呢?因为今天在进行系统上线的时候遇到了这个问题. 这次的上线动作还是比较大的,由于组织架构拆分,某个接入层服务需要在两个部门各自独立部署,以避免频繁的跨部门沟通,提升该接 ...

  8. Java多线程编程的优点和缺点

    优点: 加快响应用户的时间:多线程允许并发执行多个任务,可以充分利用多核处理器,从而提高程序的性能和响应速度.比如我们经常用的迅雷下载,都喜欢多开几个线程去下载,谁都不愿意用一个线程去下载,为什么呢? ...

  9. JavsScript对密码进行Base64加密和Base64解密

    const password = "hello"; // 进行Base64加密 let pwd64 = window.btoa(password); console.log(pwd ...

  10. OpenGL 摄像机视角详解

    1. 摄像机 摄像机就好像是我们的眼睛,我们从摄像机的方向观察世界空间中的模型.摄像机远离模型,模型自然就变小了(透视投影下),然而,在GL中事实上并没有摄像机的概念.但是我们可以通过移动世界空间远离 ...