背包 学习笔记
前言:背包学了无数遍,这次总算能记住点东西了QAQ
----------------
背包是线性DP中一类重要而特殊的模型。
0/1背包
给定$n$个物品,其中第$i$个物品的体积为$w_{i}$,价值为$c_{i}$。现在给你一个体积为$m$的背包,问怎样选择使得物品总价值最大?
我们先考虑朴素算法。
设$f[i][j]$为已经考虑了前$i$个物品,选出总体积为$j$的物品放入背包所取得的最大价值。
如果不选第$i$件物品,则$f[i][j]=f[i-1][j]$。
如果选第$i$件物品,则$f[i][j]=f[i-1][j-w_{i}]+c_{i} (j\geq w_{i})$。两者中取最大值。
考虑优化:因为在考虑第$i$件物品时只取决于考虑第$i-1$件物品时的情况,所以上面$f$数组的第一维可以省去。
即$f[j]=max(f[j],f[j-w[i]]+c[i])$。
请注意:$j$是倒序循环的。假设正序循环:比如用$j-2w_{i}$的情况来更新$j-w{i}$,此时$j-w{i}$已经过度到第$i$个阶段,再循环到$j-w{i}$时,就会发生“第$i$个阶段更新第$i$个阶段”的情况,违背了线性DP的原则。而倒序循环保证了每个物品只会被考虑一次,符合线性DP的原则。
-------------------------------
完全背包
和0/1背包差不多,只是增添了一个条件:每个物品可以被挑选无数次。
和0/1背包唯一不同的地方:$j$是正序循环的。因为每个物品都可以被选无数次。
$f[j]=max(f[j],f[j-w_{i}]+c_{i}$。
-------------------------------------
多重背包
和完全背包的条件不同:每个物品可以被选$t_{i}$次。
最朴素的方法当然是从$0$到$t_{i}$循环,每种情况都试一遍。但复杂度较高。
我们可以用二进制拆分法。众所周知,$2^0,2^1,2^2,...,2^k-1$可以表示$0$到$2^k -1$的所有整数。所以我们可以用这种方法把物品二进制拆分。设$r_{i}=c_{i}-2^0-2^1-...-2^p$,则可以拆分为$p+2$个物品,体积分别为$2^0 *w_{i},2^1 *w_{i},...,2^p *w_{i},r_{i}*w_{i}$。此方法将物品拆分为$logc_{i}$个,效率较高。
------------------
分组背包
条件变化:有$i$组物品,每组物品有$k$个,每组最多选一个物品,求最大价值。
直接让$k$循环选取即可,只要选完了就立即从第$i$个阶段过渡到第$i+1$个状态。
for (int i=1;i<=n;i++) for (int j=m;j>=0;j--) for (int k=1;k<=c[i];k++) if (j>=v[i][k]) f[j]=max(f[j],f[i-v[i][k])+w[i][k]
注意$k$循环要在$j$循环之内。
原文地址:https://www.cnblogs.com/Invictus-Ocean/p/12694265.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法