复习:0/1背包和完全背包是如何从二维数组压缩到一维的

本文详细讲解了0/1背包和完全背包问题的解决方法,包括它们的状态转移方程及从二维到一维数组的优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  从刚开始接触背包到现在,已经快两个月了,学完背包之后就又继续学其它东西,现在该回头再来复习一下,整理整理自己的思路,使自己对背包更熟练一点,这里自己先复习一下0/1背包和完全背包。

  0/1背包的主要思路就是:这件物品,取还是不取。用一个二维数组dp[i][v]来表示对第i个物品,背包容量为v时的情况。c[i]表示第i件物品的体积,w[i]表示第i件物品的价值。那么考虑第i件物品取与不取:如果不取,那么就可以转化为i-1件物品、容量仍然为v、价值没有增加的情况(dp[i-1][v]);如果取,那么转化为i-1件物品、容量减去第i件物品的体积后剩余容量、价值加上第i件物品的价值后的情况(dp[i-1][ v-c[i] ] + w[i] )。为了让背包中物品价值最大,我们取二者较大者,也就是

dp[i][v]=max{ dp[i-1][v] , dp[i-1][ v-c[i] ] + w[i] }。好了,现在思考如何将数组压缩,对于这两种情况下dp[i][v]值的改变,要么是dp[i][v]=dp[i-1][v],要么是dp[i][v]=dp[i-1][ v-c[i] ] + w[i]。假设下面是就是二维数组dp的一部分,

      a    b    dp[i-1][v]    d    e

      f    g     dp[i][v]       h          k

  我们可以发现:如果dp[i][v]=dp[i-1][v],那么相当于直接复制dp[i][v]上面的元素dp[i-1][v]值。而如果dp[i][v]=dp[i-1][ v-c[i] ] + w[i],注意到,v-c[i]<=v,所以,dp[i][v]的值是由上面红色的元素加上w[i]得到,也就是说,我们每次想要更新dp[i][v],可能会用到的值只有上面红色的部分,所以,我们就能把二维数组压缩为一维数组,只需要每次从后往前更新dp[i][v]的值。这样就用dp[v]来表示容量为v的情况下,背包内物品的价值,状态转移方程也就成了:

  dp[v]=max{ dp[v] , dp[ v-c[i] ] + w[i] }

 

  对于完全背包,一件物品可以取多次,我们仍然使用0/1背包的思想:这件物品,取还是不取。唯一的变化是,取了这件物品,还可以取。所以,如果取,仍然是i件物品的问题( dp[i][ v - c[i]] + w[i]);如果不取,dp[i][v]还是dp[i-1][v]都一样(第一次不取,以后也不会取,相当于转化成i-1件物品的问题,为了和取的情况保持一致,采用dp[i][v])。所以状态转移方程变为了dp[i][v]=max{ dp[i][v] , dp[i][ v-c[i] ] + w[i] },那么在数组里,

      a    b    m        d    e

      f    g     dp[i][v]       h          k

  同样注意到,v-c[i]<=v,所以,每次更新dp[i][v],可能用到的值是红色部分,所以也可以压缩为一维,这里要注意了,数组中的f、g,是i下的情况,并不是i-1的情况,dp[i][v]的值取决取i下,而不是i-1,所以此时应该从前往后更新dp的值,这样才能保证取第i件物品时,dp[i][v]是由dp[i][v-c[i]]+w[i]推得,所以尽管状态转移方程仍然为dp[v]=max{ dp[v] , dp[ v-c[i] ] + w[i] },v的循环顺序却应该是从小到大

 

  基本上,这就是0/1背包和完全背包从二维转化为一维的思路,以后自己还要经常复习。

  0/1背包的伪代码:

for i=1 to N
    for v=V to 0
        f[v]=max{dp[v],dp[v-c[i]]+w[i]}

  完全背包的伪代码:

for i=1 to N
    for v=0 to V
        f[v]=max{dp[v],dp[v-c[i]]+w[i]}

 

 

转载于:https://www.cnblogs.com/coredux/archive/2012/08/30/2663226.html

第一阶段:搜索算法核心突破(3.25-3.28 | 4天) 3.25-3.26:DFS基础与剪枝 学习内容:回溯模板、排列/子集生成、剪枝技巧(可行性/最优性剪枝) 真题练习: 全排列问题(第七届《凑算式》种) 迷宫路径计数(二维矩阵搜索) 3.27-3.28:BFS与连通性问题 学习内容:队列实现BFS、层序遍历、连通块计数 真题练习: 第七届《剪邮票》(DFS验证5格连通性) 岛屿数量问题(连通块计数) 第二阶段:动态规划专题(3.29-4.1 | 4天) 3.29-3.30:线性DP与递推 学习内容:爬楼梯模型、打家劫舍种、递推公式设计 真题练习: 第七届《煤球数目》(直接递推) 第十四届《接龙数列》(字符串状态转移)3.31-4.1背包DP与字符串DP 学习内容:01背包模板、滚动数组优化、最长公共子序列 真题练习: 第十二届《砝码称重》(01背包种) 编辑距离问题(字符串DP) 第三阶段:数论+贪心强化(4.2-4.4 | 3天) 4.2:质数与GCD 学习内容:埃氏筛法、欧几里得算法、因数分解 真题练习:第十二届《货物摆放》(求因数组合) 4.3:快速幂与模运算 学习内容:快速幂模板、逆元计算(选学) 真题练习:大数取模问题(如计算10^{18} \mod 710 18 mod7) 4.4:贪心策略 学习内容:区间调度、相邻交换策略 真题练习:第四届《翻硬币》(贪心翻转)、第九届《乘积最大》 第四阶段:数据结构+图论(4.5-4.7 | 3天)4.5:并查集与优先队列 学习内容:路径压缩、按秩合并、Dijkstra堆优化 真题练习:第十二届《城邦》(并查集预处理) 4.6:栈与图论基础 学习内容:表达式计算、Dijkstra最短路径 真题练习:第十二届《路径》(Dijkstra模板题) 4.7:拓扑排序与最小生成树 学习内容:Kahn算法、Kruskal实现 真题练习:第十四届《飞机降落》(拓扑排序思想)第五阶段:二分+综合复习(4.8-4.10 | 3天) 4.8:二分查找与答案 学习内容:边界处理、最大值最小化问题 真题练习:第十二届《直线》(排序去重+二分优化) 4.9-4.10:全真模拟与查漏补缺 任务:限时刷近3年真题(重点做搜索、DP、数论题) 错题复盘:整理易错代码片段(如DFS状态遗漏、DP初始化错误)时间完全不够 我3.25-3.29都没把DFS要学习的内容学完也还没加以联系,这份安排太紧凑了,难以让我真的深入理解这些算法,只能明白个模板,帮我再做一份学习计划吧,可以删减些比赛出现可能性相对较低的算法或者算法中的学习内容,以求留下广东省十六届以前蓝桥杯c赛道b组出现频率最高能覆盖尽量多考试类型的算法,帮我再精简筛选一下,然后按照在2025年广东省蓝桥杯c赛道b组可能出现的频率的顺序帮我重新安排一下学习内容,以助我拿下奖项。从3.30开始给我从新安排一下,现在学了DFS的迷宫,全排列,回溯模板,但还没加以真题练习
最新发布
03-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值