zoukankan      html  css  js  c++  java
  • 动态规划 笔记

    动态规划 笔记

    一、本质

    动态规划的本质是状态压缩(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] imes C_{frac{n-n mod m^2}{m}+j-1}^{j-1} ]

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

    • [ ] #### (O(n^3))不知道能不能做

    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] imes j)
    3. 一个人把两个联通块合了起来 (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 个物品, 体积分别是 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])的格子总共只被染一次 问方案数

    这样就搞定了

  • 相关阅读:
    Unity 预处理命令
    Unity 2DSprite
    Unity 生命周期
    Unity 调用android插件
    Unity 关于属性的get/set
    代码的总体控制开关
    程序员怎么问问题?
    VCGLIB 的使用
    cuda实践(1)
    python之json文件解析
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9403438.html
Copyright © 2011-2022 走看看