区间dp总结

前言

上个坑还没填(悲

区间 dp

区间 dp 是指这样一类动态规划:算法在一个线性序列上进行,且可以通过小区间转移到大区间。

正因如此,一般的区间 dp 数组至少是两维: dp[N][N] ,其中前面一位表示区间左端点,后面一维为区间右端点。

因为要枚举区间,它的时间复杂度至少是 $O(n^2)$ ,事实上大多数时候对单个区间进行转移是要枚举断点的,时间复杂度将来到恐怖的 $O(n^3)$ 。

判断一个题是不是区间 dp ,从问题是否在一个序列上和数据范围是不是很小就可以了。

以上都是废话。当年讲 dp 基础的时候也讲过一些简单的区间 dp ,今天的博客实质上是对最近做的一些新颖的区间 dp 题目做一些归纳,并探讨我们能从这些题中学到什么。

例题

NKOJ P10533

题意:给你一个只含加号、减号、乘号的表达式,你可以按照任意顺序计算这个表达式,求最后所有结果的和。 $1 \leq n \leq 500$ 。

容易想到区间 dp 。设 dp[i][j] 表示这段区间能计算得到的所有值之和。

对于每个区间 $i, j$ ,我们枚举断点 $l \leq k < r$ 。

假设左边能够得到的所有结果是

$$ {res_1, res_2, \dots, res_{cnt_1}} $$

右边是

$$ {res2_1, res2_2, \dots, res2_{cnt_2}} $$

易得一个区间能够计算得到的结果有它的长度减一的阶乘个。

我们需要把两边的结果两两配对,而我们现在只知道左边的和和右边的和。

分情况讨论:

  • 乘号:直接左边乘上右边,展开后发现两两配对了。

  • 加号: 因为每个左边的数要与右边 $cnt_2$ 个数都配对一次,所以每个数都要乘上右边的长度。 右边同理。左边的和乘上右边的个数,加上右边的和乘以左边的个数。

  • 减号:加号同理,左边的和乘上右边的个数,减去右边的和乘以左边的个数。

好的,但是写完后发现样例都过不去。

手推样例会发现有些重复的数只被算了一次。当然我没那个能耐手推,我打的表。

这是为什么呢?

其实我们在左右合并计算结果时忽略了一个问题:左右计算的相对顺序。

我们知道左边内部计算的固定顺序(因为要得到某个固定结果),也知道右边的。

但是左右的计算可以交替进行啊!

所以我们需要枚举左右计算的相对顺序。

形式化地,确定一个长度为两区间运算符之和的序列 $s$ , $s_i \in \left \{ 0, 1 \right \} $ 的个数,其中 0 有左边的运算符个数个,1 有右边的运算符个数个。0 表示左边的,1 表示右边的。不需要管左边与右边内部的计算顺序,因为这是我们已经计算过了的。

我们考虑把这么多个 0 和 1 随机打乱构成全排列,则有 $(r - l - 1)!$ 个。

但是我们要把 1 和 0 内部构成的全排列除去。于是最终要乘上的常数就是:

$$ \frac{(r - l - 1)!}{cnt_{1}!cnt_{0}!} $$

用逆元计算即可。

总结:在设计方程时应当考虑区间合并后的影响,例如排列可能会被打乱。

本文作者:aaaaaaqqqqqq

本文链接:https://www.cnblogs.com/aaaaaaqqqqqq/p/17976948

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   aaaaaaqqqqqq  阅读(11)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.