动态规划 笔记
一、本质
动态规划的本质是状态压缩(by Scape)
状态压缩只和答案有关的值
所以dp是一个不断探索问题性质,减少和答案有关的值的个数
二、类似背包的dp
有多少不同的序列 和为([Math Processing Error]n) 并且任意两个数([Math Processing Error]mod m)都互不相同
两个序列不同当且仅当他们长度不同或者某个位置上的数不同
(m leq 100)
首先我们发现 序列的长度最多为m 因为他们(mod m)两两不同
那么我们可以把这最多m个数全部设定为0~m-1之间 最后在在某一些上面加上m的倍数 一直加到n
这样我们可以设计出一个状态 (f[i][j][k])表示当前考虑到(i)这个数 当前选了(j)个数 当前选的数的和(mod m=k)的方案数
那么我们呢可以做出一个(O(n^4))的dp
计算答案:
后面的组合数是用隔板法做出来的
- [ ] #### (O(n^3))不知道能不能做
SRM 625
(n)个座位的圆桌 (k)个人坐 任意时刻联通块数量(leq G)
求方案数 (n,k,G leq 2000)
先瞎写一个dp
令(f[i][j])表示坐了(i)个人 有(j)个联通块的方案数
那么考虑三种情况
- 一个人坐进去 左右都没有人 (f[i][j]+=f[i-1][j-1])
- 一个人坐在一个联通块的边上 联通块个数不变 (f[i][j]+=f[i-1][j] imes j)
- 一个人把两个联通块合了起来 (f[i][j]+=f[i-1][j+1] imes j)
结果就对了
这样转移为什么就可以了呢
我们把人坐下去转化成在人之间插空格
那么如果当前有(j)个联通块并且总座位数-总人数(geq j)
那么一定有一种插空格的方式
所以我们在dp的时候 按照上面的方程式dp 并且记得在联通块数量(gt G) 或者总座位数-当前人数(lt j)的时候不计算 就可以了
当然这不是答案 因为空格的位置可以自己定 所以(i)个人 (j)个联通块 那么我们还有(n-i)个空格 需要放进(j)个联通块之间的缝隙中 那么就是(C_{n-i-1}^{j-1})种放法 乘上方案数就好了
复杂度(O(kG))
BZOJ2287
ftiasch 有 N 个物品, 体积分别是 W1, W2, …, WN。 由于她的疏忽, 第 i 个物品丢失了。 “要使用剩下的 N – 1 物品装满容积为 x 的背包,有几种方法呢?” — 这是经典的问题了。她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i, x) 表格。
如果没有去掉一个物品的条件 那么就是一个经典的背包问题
这样的问题我们称为"退背包"
首先还是找出dp数组
(f[i][j])表示前(i)个物品 占用容积为(j)的方案数
(f[i][j]=f[i-1][j]+f[i-1][j-w[i]])
现在我们需要第(i)个物品不选
那么我们用总数-第i个物品选的方案数
所以我们用(c[i][j])表示题目中的(count(i,j))
分类讨论
- (j geq w[i]) 这个时候(c[i][j]=f[n][j]-c[i][j-w[i]])
- (j lt w[i]) 这个时候(c[i][j]=f[n][j]) 肯定不会用到第(i)个物品
那么就做完了
有 (N) 个点, 每个点有一个权值 (A_i) . 现在要把这 (N) 个点连成一棵树, 设第 (i) 个点在树中的度数为 (d_i) , 那么这棵树的权值为 (prod^N_{i=1} {{A_i}^{d_i}}) .
求所有可能的树的权值之和模 (10^9 +7) 的结果. ((N ≤ 2000, Ai ≤ 1000000)).
首先一堆点连成一棵树的所有情况可以想到prüfer序列
我们要求
中间那个分数就是这种度数序列出现的种数
我们用(f_{i,j})表示当前考虑前(i)个点 前(i)个点的度数和为(j)的对应的上面式子的值
那么枚举当前点的度数来转移 可以做到(O(n^3))
怎么优化呢?
讲道理想不到...
bzoj 4753
(N)个人 每个人都由一个编号比他小的人推荐 选(K)个人 满足如果选了(A) 那么推荐(A)的人也得选 每个人有两个值 价值和代价 求总价值与总代价的比值的最大值
这题很好做 首先分数规划 二分答案之后 每一个人都用他的价值-代价×当前答案
然后这题就变成了选一些人 满足...条件 并且每个人都有一个权值 求是否能选出一些人 这些人的权值之和>0
这是一件很好做的事情
令(f[i][j])表示当前考虑到(i)号点 以(i)为根的子树中选(j)个点且满足要求的最大权值
那么更新也很容易 (f[i][j]=max(f[i][j],f[i][j-k]+f[nwson][k])
这是(O(n^2 log n))的 可以通过这道题
SRM 613
给一个棋盘染色 每列最多染一次 每行所有列数(leq L[i])的格子总共被染一次 每行所有列数(geq R[i])的格子总共只被染一次 问方案数
这样就搞定了