动态规划 笔记

动态规划 笔记

一、本质

动态规划的本质是状态压缩(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

\[f[i][j][k]=f[i-1][j-1][k-i] + f[i-1][j][k] \]

计算答案:

\[ans=\sum f[m-1][j][n \mod m^2]\times C_{\frac{n-n \mod m^2}{m}+j-1}^{j-1} \]

后面的组合数是用隔板法做出来的

SRM 625

\(n\)个座位的圆桌 \(k\)个人坐 任意时刻联通块数量\(\leq G\)

求方案数 \(n,k,G \leq 2000\)

先瞎写一个dp

\(f[i][j]\)表示坐了\(i\)个人 有\(j\)个联通块的方案数

那么考虑三种情况

  1. 一个人坐进去 左右都没有人 \(f[i][j]+=f[i-1][j-1]\)
  2. 一个人坐在一个联通块的边上 联通块个数不变 \(f[i][j]+=f[i-1][j]\times j\)
  3. 一个人把两个联通块合了起来 \(f[i][j]+=f[i-1][j+1]\times 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 个物品, 体积分别是 W1W2, …, 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)\)

分类讨论

  1. \(j \geq w[i]\) 这个时候\(c[i][j]=f[n][j]-c[i][j-w[i]]\)
  2. \(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序列

我们要求

\[\sum_{d_1+d_2+d_3+\ldots+d_N=2N-2}{\frac {(N-2)! \cdot d_1 \cdot d_2 \cdot d_3 \cdots d_N}{(d_1-1)! \cdot (d_2-1)! \cdot (d_3-1)! \cdots(d_N-1)!} \cdot {A_1}^{d_1} \cdot {A_2}^{d_2} \cdot {A_3}^{d_3} \cdots {A_N}^{d_N}} \]

中间那个分数就是这种度数序列出现的种数

我们用\(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]\)的格子总共只被染一次 问方案数

这样就搞定了

posted @ 2018-08-01 19:16  wawawa8  阅读(317)  评论(0编辑  收藏  举报