福州0209 DAY5 动态规划模型

真正的巨坑,一寒假都写不完,慢慢来。
另,上课的学长(叫老师真的显得好老))好温和啊,这几天来第一次听这么透彻,甚至突然想好好学习一晚上。………………


基本要素

阶段:把所给求解问题的过程恰当地分成若干相互联系的阶段。
一般是按某种线性关系划分的,比如时间先后etc。

状态:表示每个阶段的自然状况/客观条件,是不可控制因素。
……教材上的说法太学究了,就是表示决策目前的一个状态,字面意思。

状态转移:从一个阶段的一个状态转移到下一阶段的某个状态的一种选择行为。
也就引出了这种选择的标准,状态转移方程。……


一些性质

最优化原理:无论过去状态和决策如何,对前面的决策所形成的状态而言, 余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。
一个问题满足最优化原理又称具有最优子结构。

dp和贪心都是从局部最优解推出全局最优的算法,而且同样具有最优子结构。然而贪心的最优只对当前做的这一步选择负责,即它只保证在当前的选择中这一步是最优的,所以贪心的全局正确性要严格的证明。而dp则是每时每刻保证过去的局部都是最优的,并逐步扩大问题规模,而且一般能记录子问题最优解。
*我不知道,我瞎说的。*

tip:当发现设置的状态无法满足最优子结构时,通常咳采用增加状态维度的方法。

无后效性:当前状态是此前历史的完整总结,过去只能通过当前状态影响之后的过程。
……贪心是有后效性的。

子问题重叠性:dp实际上是搜索的优化,将指数级的搜索算法改进为有多项式复杂度的算法。它的根本目的在于解决了搜索中大量重复的子问题(记忆化搜索,我们把那些重复的问题作为状态存下来了),所以这是一种空间换时间的技术。
*dp的子问题是相对于全局而言、逐渐扩大范围直至全局的,而分治是把总问题拆成一堆区间单独处理。


  • 区间dp

    字面理解,每段区间的最优值都是从更小区间的最优值得到的。这是分治思想的一种应用。
    基本状态:f[i] [j] 表示第i个元素到第j个元素这个区间的最优值。

    hdu4632

    求字符串有多少回文子序列。

    首先,明确概念…………子序列是从原序列中随意揪出一堆数字组成的序列(相对顺序不变),而子串才是要求连续的那个东东。

    dp[i][j]表示从i到j的子序列中回文子序列的个数。

这里写图片描述

……
故得状态转移方程:dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]。
当然,在这个大区间计算的时候,如果s[i]==s[j],那么显然dp[i][j] += dp[i + 1][j - 1] + 1.

POJ 2955

给出一个括号字符串,问这个字符串最长合法子序列长度。若A、B合法,则AB;(A)合法。

dp[l][r]表示[l,r]中最长合法子序列长度。

则有状态转移方程:
if(s[i]==s[j]) dp[l][r]=dp[l+1][r-1]+2.
dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]).枚举k。

比如,(()[ ()],假设k是空格前一位。则dp[l][k]=2,dp[k+1][r]=2,此时dp[l][r]=4,但是当k再前移一位时,dp[l][k]=2,dp[k+1][r]=4,dp[l][r]=6.

为什么不在dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r])之后判断若s[i]==s[j],dp[i][j]+=2?
因为dp[l][k]可能已将s[l]匹配了另外的某个括号,dp[k+1][r]同理,故不可行。
那如果把转移方程改为dp[l][r]=max(dp[l][r],dp[l+1][k]+dp[k+1][r-1])再判断吗?也不行,因为存在dp[l][k]+dp[k+1][r]可能更优的情况。

所以,如果一定要先状态转移再判断,那么:
dp[i][j]=max(dp[i][i+k]+dp[i+k+1][j])
if(s[i]==s[j]) dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2).

……说这么多其实没什么特别的意义。

  • 环形DP-特殊的区间DP

它其实是一个首尾相连的区间。

Codevs 2102 合并石子

在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。试设计算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

第一步,断环为链,即将链复制一遍。a[i+n]=a[i].
d[i][j]表示合并第i到第j堆的最高得分。以区间长度为关键字升序计算。

  • 状压dp

    为什么需要状态压缩?因为很多状态不易表示,所以我们用某种特定的方法来让它转变为一个可快速表示的东东。
    例如经典的一笔画问题。我们将状态设定为每个点是否被走过,显然这难以表示。所以我们用二进制表示——比如说有五个点,1、3、4已走过,那么我们可以表示成:10110,转化为十进制即22.
    这种方法也用于搜索等等等等。
    真的很绝妙、很优雅啊!

多米诺骨牌覆盖

n*m的矩阵,用1*2的骨牌完全覆盖,骨牌不重叠。求不同的覆盖方法总数。模p。m<=5=,n<=10000.

怎么表示状态呢?m很小,完全可以状压。例如,5*4的矩阵,由于第2行的影响,第3行的第2、3列已经被牌占据了,那么用二进制表示即为0110.

f[i][j]表示第i行状态为j时的方案总数。

如何实现状态转移?我们先通过搜索,预处理一个数组g[x][y],表示从x状态变为y状态的方法数。
于是f[i][j]=Σf[i-1][k]*g[k][j];枚举k状态。

O(n*2^m*2^m),常数写小一点应该ok。

noip2016 愤怒的小鸟

题目大意:用过原点的抛物线覆盖n个坐标点,求最少需要的抛物线数量。n<=18.

根据初中数学,三点确定一条抛物线。原点已知,故枚举剩下两个点。
p[j]表示枚举的第j条抛物线。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值