首页 > 其他分享 > DP查缺补漏之01背包优化原理

DP查缺补漏之01背包优化原理

时间:2023-11-01 11:11:06浏览次数:35  
标签:状态 补漏 01 枚举 DP 查缺 最优 转移 dp

DP查缺补漏之01背包优化原理

先复习一下基本知识

  • 状态假设
    • DP[I][J]为前\(i\)个物品,容量小于\(j\)时的最优解(最大价值)
  • 状态转移
    • DP[I][J] = max(DP[I - 1][J], DP[I - 1][J - V[I]] + W[I])
      • 对于第\(i\)个物品,两种可能
        • 装入背包
          • 则状态应通过前\(i - 1\)个物品,容量小于\(j\)时的最优解再加上W[I]​转移,但是实际上本次状态的容量才为\(j\),若直接从DP[I-1][J]转移则忽略了该物品体积,所以应从减去该次物品体积的DP[I - 1][J - V[I]]转移。即DP[I - 1][J - V[I]] + W[I]
          • 证明此解严谨性
            • 上一层循环已然计算了DP[I - 1][0 ~ M]的所有最优解
            • DP[I - 1][J - V[I]]已经是最优解
        • 不装入背包
          • 则状态应通过前\(i - 1\)个物品,容量小于\(j\)时的最优解直接进行转移
  • 代码处理
    • 开二维数组来对标状态假设
    • 初始化DP[0][0~M]为\(0\)
    • 两层循环递推,外层枚举\(1 \sim i\),内层枚举$ 1 \sim m $
    • 进行DP[I][J] = DP[I - 1][J - V[I]] + W[I]状态转移时必须确保\(J > V[I]\)

优化思路(空间)

  • 从状态转移方程入手

    • DP[I][J] = max(DP[I - 1][J], DP[I - 1][J - V[I]] + W[I])
      • 每个DP[I][J]都是从DP[i-1][x]转移而来
      • 显然可以用滚动数组
  • 具体化优化思路

    • 直接删除第一维

      • 用循环来直接进行对上一维的转移

      • for(int i=1;i<=n;i++)
        {
        	for(int j=W[i];j<=M;j++)
        	{
        		dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        	}
        }
        
      • 但这有一个问题,此时的dp[j - w[i]]实际上就是本次\(i\)的,因为是从小到大递推的,要操作每一个dp[i - 1][j]的时候都已经被更新成此次状态的dp[i][j]了,此时需要一个妙手,第二层循环反着枚举

      • for(int i=1;i<=n;i++)
        {
        	for(int j=M;j>=w[i];j--)
        	{
        		dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        	}
        }
        
      • 因为所有大的都是由小的转移而来,由大至小的枚举使得每一次要取dp[j-w[i]]时,dp[j-w[i]]都是\(i\)上一次循环的最优解,不会被更新。

标签:状态,补漏,01,枚举,DP,查缺,最优,转移,dp
From: https://www.cnblogs.com/kdlyh/p/17802581.html

相关文章

  • 【2023-11-01】一款基于 pdf.js 的 PDF 批注注释插件库(纯JS、高亮、画笔、多边形、历
    基于纯JavaScript和PDF.js做的一款PDF批注拓展插件-PDFMaster,一款仍能兼容支持IE11的PDF批注插件,界面美观功能强大,有无开发经验都可以快速简单快速使用。Demo及源码Demo和源码地址:https://demos.libertynlp.com功能演示视频:https://www.bilibili.com/video/BV12C4y1n7TL......
  • P5070 [Ynoi2015] 即便看不到未来
    题意给定一个序列,静态区间查询区间的长度为\(1\to10\)的极长值域连续段个数。Sol考虑离线下来跑扫描线。枚举右端点,维护每个左端点的答案。不难想到,\(i\)对\(lst[i]\)是没有贡献的,考虑右端点为\(i-1\),若此时的\(l\lelst[i]\)。\(i\)不作贡献。所以我们把值域上......
  • AT_joisc2012_constellation 星座
    题目传送门更好看的题面非常巧妙的凸包。题目分析这道题的本质就是将所有点划分为两个生成树,求可能的方案数。part1求凸包的答案我们可以考虑先求一个整体的凸包,如下图:其中红色的点为星座$A$,蓝色的点为星座$B$,黑色的点不确定。先考虑凸包上的点,对于凸包上的点,当存在......
  • PAT_A1015 Reversible Primes
    A reversibleprime inanynumbersystemisaprimewhose"reverse"inthatnumbersystemisalsoaprime.Forexampleinthedecimalsystem73isareversibleprimebecauseitsreverse37isalsoaprime.Nowgivenanytwopositiveintegers N (&......
  • P5659 [CSP-S2019] 树上的数
    相信大家都看过题,但还请搞清楚是数对应结点编号。这里用\(a_i\)表示\(i\)号结点对应的数。对于\(n\leq10\)的数据,全排列出删边的顺序然后模拟,取字典序最小的方案。对于菊花,仍然考虑删边的顺序,假设删边依次是\(rt\tov_1,rt\tov_2,\cdots,rt\tov_{n-1}\)。因为每删一......
  • P3320 [SDOI2015] 寻宝游戏
    其实就是动态维护包含所有关键点的极小联通子树边权和。暴力做法只要子树内有关键点就去遍历,所以按照DFS序顺序去遍历这些关键点肯定是没问题的。用set维护即可。在\(x\)和\(z\)之间加入\(y\),答案加上\(dis(x,y)+dis(y,z)-dis(x,y)\),删除就反过来。......
  • P5666 [CSP-S2019] 树的重心
    考虑一个结点在什么情况下会成为重心。随便钦定一个根结点。对于结点\(u\),假设割掉了其子树\(v\)中的某条边或连接\(u\)和\(v\)的边,形成了一棵大小为\(k\)的新树。令\(mx\)表示除\(v\)子树外最大的子树大小(或\(n-siz_u\))。如果\(u\)成为了重心根据定义有\(2\ti......
  • P3233 [HNOI2014] 世界树
    将关键点以深度为第一关键字,编号为第二关键字从小到大排序。建完虚树后依次考虑这些关键点可能的管辖的结点。每次在虚树上向上跳,当遇到某个已经被访问过的结点时,根据我们的排序条件,显然再往上的结点就一定不是当前关键点管辖的了。但是在向上跳的这条链上的子树内的结点不一定由......
  • P1232 [NOI2013] 树的计数
    首先要明确,对于一个结点,其儿子的遍历顺序是确定的,在DFS序和BFS序中相同。而BFS序更容易确定一棵树的深度,只需要知道在哪些结点分了层。所以可以通过DFS序来确定BFS中的分层方案。然后分类讨论:\(BFS_u+1=BFS_v\),\(DFS_u>DFS_v\),相差恰好一层。若同层则说明DFS先进......
  • 解题报告 P3704 [SDOI2017] 数字表格
    P3704[SDOI2017]数字表格经典莫反。题目要求:\[\prod_{i=1}^n\prod_{j=1}^mfib(\gcd(i,j))\]不妨令\(n<m\)。套路地,我们设\(\gcd(i,j)=d\),然后枚举\(d\):\[\begin{aligned}&\quad\prod_{d=1}^n\prod_{i=1}^n\prod_{j=1}^mfib(d)^{[\gcd(i,j)==d]}\\&=\pr......