背包 dp
顾名思义,就是给你一个背包,然后给你一些物品,有一定的限制条件,然后求获得的最大值。
Part1 01背包
P1048 采药
大意:给一个背包,每个物品有对应的价值,重量(本题中时间就是重量),在背包容量下(采药的时间),求最大价值。
01 背包二维方程
dp[i][j]=max(dp[i−1][j],dp[i−1][j−w[i]]+c[i])
稍微解释一下,dp[i][j] 前 i 个物品,取 j 的容量可以获得的最大价值。
dp[i−1][j] 表示我不选当前这一件物品。
dp[i−1][j−w[i]]+c[i] 表示我选当前这一件物品,首先我需要腾出 w[i] 的空间,也就是 j−w[i] 同时当前物品占一个位置,也就是 i−1 最后,可以获得 c[i] 的价值。
然后考虑压维。
直接设 dp[j] 表示重量为 j 是可以获得的最大值。
dp[j]=max(dp[j],dp[j−w]+c)
(边输入边进行处理)
for(int i=1;i<=n;i++)
for(int j=m;j>=w;j--)
dp[j]=max(dp[j],dp[j-w]+c);
从后往前枚举是防止重复。原因是如果是从前往后的话,可能会出现在同一个 i,dpj 被更新一次,dpj+w 再被更新一次,那这个物品就被取了两次,就不符合 01 背包了。
方程的解释和上面基本雷同,就不多说了。
Code
练习:AT4526
_JF_的题解
Part2 完全背包
P1616 疯狂的采药
完全背包和 01 背包不同的地方,就是物品有无数件。
所以状态就不再是取或不取,而是取 0 件,1 件,2 件... n件。
先考虑朴素算法 dp[i][j] 表示前 i 件物品,消耗 j 的空间,所可以获得最大值。
dp[i][j]=max(dp[i][j],dp[i−1][j−w[i]×k]+k×c[i])
我们只要再多一层循环,枚举件数即可。
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<=j/w[i];k++)
dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]*k]+k*c[i]);
接着考虑压维。
dp[j] 表示背包容量为 j 时,所获得的最大价值。
方程就是
dp[j]=max(dp[j],dp[j−w]+c)
但是要注意,这里的 j 要从正序开始枚举。
for(int i=1;i<=n;i++)
for(int j=w;j<=m;j++)
dp[j]=max(dp[j-w]+c,dp[j]);
Part3 多重背包
和完全背包不同的是,这里有限制物品的数量。
P1776 宝物筛选
先考虑简单的方法。
思路:我将每件物品分成 取 0,1,2...n 件,然后对取这一些件数进行 01 背包。
dp[i][j]=max(dp[i−1][j],dp[i−1][j−k×w[i]]+k×c[i]
然后考虑压维,就是
dp[k]=max(dp[k],dp[k−w[i]]+c[i])
for(int i=1;i<=n;i++)
for(int k=m;k>=v[i];k--)
dp[k]=max(dp[k],dp[k-w[i]]+c[i]),ans=max(ans,dp[k]);
时间复杂度为O(V×∑n[i])
但是,我们可以进行优化:
首先引入一个定理:对于任意正整数 x,都可以用这个式子表示:
20+21+22+...+2k+s
s 表示 x−20...−2k 的剩余部分。
那就说明,我们只用枚举这一些数(20,21 等),并进行组合,加和,就可以轻松将 0 到 n[i] 之内所有的数表达出来。
这就对我们的这一行进行了优化。
for(int j=1;j<=n[i];j++)
对于 20+21+22+...+2k+s,我们只需要 log(n[i]) 的时间预处理即可。
O(V×∑log n[i])
Code
P1833 樱花
稍微变形。
对于“可以看无数次”,看上去是完全背包,但是由于时间有限制,他最多可以看 m/w[i] 次,于是就转换了。
Code
Part 4 二维费用背包
P1910 L国的战斗之间谍
相较于 01 背包,就是多了一些限制条件。
01 背包的限制条件是重量。
但是二维费用背包就是有两个限制条件。
也可能会有更多(那就多加几维)即可。
对于这一题而言,我们设 dp[i][j][k] 表示前 i 个人花费 j ,k 代价以后所获得的最大值。
dp[i][j][k]=max(dp[i−1][j][k],dp[i−1][j−t[i]][k−w[i]]+c[i])
通过观察,我们可以发现这一类题的套路:
每加一个限制条件,就多加一维,多加一层循环,以及 [l−k[i]] 这样子的 01 背包模式。
当然,我们可以压去 i 这一维。
Code
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现