经典揹包问题
01揹包和无限揹包略过
多重揹包的优化
这能优化到O(nm)?!
(我们以求方案数为例)
设第i种物品有c[i]个,重量为w[i]
f[i][j]=∑k=0c[i]f[i−1][j−k⋅w[i]]
这是最基本的暴力,然后考虑优化
我们写一个类似前缀和的东西
设g[i][j]=f[i−1][j]+g[i−1][j−w[i]]
那么f[i][j]=g[i][j]−g[i][j−(k[i]+1)⋅w[i]]
自此可以优化到O(nm)
Ps:若用二进制拆分来优化,就不能统计方案,比如说对于5会拆成{1,2,2},那么再算选两个时就会统计两次。
小习题:
1. 考虑01揹包问题,有Q种操作,每次加入一种物品或删除一种物品,每次操作完后输出不超过S的方案数
n,Q,S≤2000
我们假设这个数重量为w
对于加入这个数的操作:
for i:S downto wf[i]+=f[i−w]
对于删除这个数的操作:
for i:w to Sf[i]−=f[i−w]
时间复杂度:O(nS)
2. 树上依赖01揹包:如果儿子选了,则父亲必须要选
这是一个很强的限制
思考后就会发现,这相当于在树上选择一个包含根节点的连通块
那么我们通过dfs序把原问题转化到序列上
我们设f[i][1]表示选第i个点,f[i][0]表示不选第i个点
考虑f[i][1]的转移 f[i][1]+=f[fa[i]][1]
考虑f[i][0]的转移 f[i][0]+=f[ed[i]−1][0]
(未完待续)