背包基础小结
背包学得太差了要好好复习总结一下 : )
\(01\)/完全 背包
背包问题:有一些物品,每个物品有花费和价值,一般来说求的是在花费不超过给定数的前提下求最大的价值.
一般来说会省略第一维,但是在一些问题转化成的背包问题中不要忘了这一维可能又会被利用起来.
//01背包 v表示花费 w表示价值
go(i,1,n)
yes(j,t,a[i].v)
f[j]=max(f[j],f[j-a[i].v]+a[i].w);
//完全背包
go(i,1,n)
go(j,a[i].v,t)
f[j]=max(f[j],f[j-a[i].v]+a[i].w);
多重背包
每种物品有\(d_i\)件.
1.暴力拆分.
将物品拆成\(\sum d_i\)件,然后跑\(01\)背包.
2.二进制拆分.
将物品拆成\(\sum log\ d_i\)件,然后跑\(01\)背包.
3.单调队列优化.
我又忘了\(.jpg\),而且发现没有好好讲过单调队列优化多重背包,所以这里详细讲下叭.
发现\(f_{i,j}\)一定是从\(f_{i,j-k\cdot v_i}\)转移而来,\(f_{i,j+1}\)一定从\(f_{i,j+1-k\cdot v_i}\)转移而来,这两者的候选集合并不重合,也就是说当\(i\)确定时,它们两个是不互相影响的.
考虑将\(j\)按照除以\(v_i\)的余数分个类,一类里的某个状态\(j\)的候选答案集合一定也是属于该状态,所以我们依次在每一类里从小到大地求\(f_j\).
具体来说,我们把枚举\(j\)的一层变成先枚举余数\(u\),再从小枚举\(j\%v_i=u\)的\(j\),其实这里只要枚举一个\(p\in[1,(m-u)/v_i]\),这样枚举得到的状态\(j\)就是\(p\cdot v_i+u\).
转移:\(f_{p\cdot v_i+u}=max_{\ p-d_i\leq k\leq p-1}\{f_{k\cdot v_i+u}+(p-k)\cdot w_i\}\)
将外层循环\(i,u\)看成定值,只要维护一个随着\(k\)的减小,\(f_{k\cdot v_i+u}-k\cdot w_i\)递减的单调队列就可以了.
il int calc(Ri k,Ri i,Ri u){return f[k*a[i].v+u]-k*a[i].w;}
go(i,1,n)
{
Ri v=a[i].v,w=a[i].w,d=a[i].d;
go(u,0,v-1)
{
Ri l=1,r=0,mx=(m-u)/v;
yes(p,mx-1,max(mx-d+1,0))
{
while(l<=r && calc(q[r],i,u)<=calc(p,i,u))--r;
q[++r]=p;
}
yes(p,mx,1)
{
if(p-d>=0)
{
while(l<=r && calc(q[r],i,u)<=calc(p-d,i,u))--r;
q[++r]=p-d;
}
while(l<=r && q[l]>p-1)++l;
if(l<=r)f[p*v+u]=max(f[p*v+u],calc(q[l],i,u)+p*w);
}
}
}
树形背包/有依赖的背包问题
例题:洛谷\(1024\) 选课.
大致思路就是,对每个子树都\(dp\)一遍,将答案集中要子树的根结点,层层解决.具体来说,设\(f_{i,j}\)表示在以\(i\)为根的子树内选择了\(j\)个物品的最大价值(这里规定物品的体积都为\(1\)),转移的话就直接枚举子结点\(k\)用\(f_{k,j'}\)转移即可,注意枚举顺序是\(01\)背包的枚举顺序.
背包方案计数
\(01\)背包计数,例题:洛谷\(1164\) 小\(A\)点菜.
设\(f_{i,j}\)为前\(i\)个物品,选了的物品的体积总和为\(j\)的方案数.转移考虑能不能和选不选当前的物品就行.显然是可以省略掉第一维的,并且省略之后转移更简单一些.
完全背包改下枚举顺序就可以了叭.
习题
希望有神仙可以推荐背包题!!就稍微有点绕的一看看不出是背包的那种就行!!
\(NOIp2018\) 货币系统
考虑删掉一种货币的条件是它能被其他货币表示出来,设\(f_i\)表示数\(i\)能否被表示出来,完全背包一下,\(over\).
\(NOIp2014\) 飞扬的小鸟
一道完全背包和\(01\)背包的混合题\(QwQ\).设\(f_{i,j}\)表示到达位置\(i\),高度为\(j\)所需的最小点击数目.似乎细节很多,虽然去年写过不过还是打算再写一遍\(QwQ\).但我现在暂时不想写了\(QwQ\).
原文地址:https://www.cnblogs.com/forward777/p/11727110.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 数组属性和方法
- Android绘制系统简介
- E: Sub-process /usr/bin/dpkg returned an error code (1) 解决方案
- Linux 如何使用包管理器安装 Node.js
- CSS画图
- R语言聚类算法的应用实例
- Python时间序列选择波动率预测指数收益算法分析案例
- Linux 常用系统工作命令-date
- R使用LASSO回归预测股票收益
- Linux 常用系统工作命令-reboot、poweroff、wget
- Node.js + Socket.io 实现一对一即时聊天
- Linux 常用系统工作命令-ps、top
- Python之LDA主题模型算法应用
- R语言highfrequency高频金融数据导入
- IIS配置优化
- R语言做复杂金融产品的几何布朗运动的模拟