区间dp
这篇博客持续更新中…
对区间dp的简单介绍:
区间dp也属于线性dp中的一种,它以“区间长度”作为dp的“阶段”,使用两个坐标(区间的左、右端点)描述每个维度。在区间dp中,一个状态由若干个比它更小且包含于它的区间所代表的的状态转移而来,因此区间dp的决策往往就是划分区间的方法。区间dp的初态一般就又长度为1的“元区间”构成。
P1880 [NOI1995]石子合并:
洛谷:P1880 石子合并
题目描述
在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。
输入格式
数据的第 1 行是正整数 N,表示有 N 堆石子。
第 2 行有 N 个整数,第 i 个整数 ai 表示第 i 堆石子的个数。
输出格式
输出共 2 行,第 1 行是最小得分,第 2 行是最大得分。
分析:
若最初的第 l 堆石子和第 r 堆石子被合并成一堆,则说明 l ~ r 之间的每堆石子也已经被合并,这样 l 和 r 才有可能相邻。因此,在任意时刻,任意一堆石子均可以用一个闭区间[l, r]来描述,表示这堆石子是由最初的第 l ~ r 堆石子合并而成的,其重量为 ∑ j = l r A [ i ] \sum_{j = l}^{r}A[i] ∑j=lrA[i]另外,一定存在一个整数k (l ≤ k < r),在这堆石子形成之前,先有第1 ~ k 堆石子(闭区间[l,k]) 被合并成一堆,还要有第k + 1~r 堆石子(闭区间[k + 1,r])被合并成一堆,然后这两堆石子才合并成[L, r]。
对应到动态规划中,就意味着两个长度较小的区间上的信息向一个更长的区间发生了转移,划分点 k 就是转移的决策。自然地,应该把区间长度 len 作为dp的阶段。不过,区间长度可以由左端点和右端点表示出,即len = r - l + 1。本着动态规划“选择最小的能覆盖状态空间的维度集合”的思想,可以只用左、右端点表示dp的状态。
接下来我们先不考虑每堆石子的环形结构,先分析每堆石子是排成一排时的情况:
基于两个长度较小的区间上的信息向一个更长的区间发生了转移的思想,首先,我们要不断从较短的区间求到较长的区间,所以从 2 ~ n 枚举区间的长度,当我们确定了区间长度的时候,再枚举左端点 l ,由于区间长度是确定的,所以右端点 r 也被确定了。接着,因为我们已经确定了某个特定的区间,接下来就是枚举区间的分割点 k ,所以每个区间(l ~ r)的得分是左区间(l ~ k)的得分 + 右区间(k + 1 ~ r)的得分 + 两个区间的石子合并时候的得分。
先讨论合并所有石子之后的最小得分,设F[l, r]表示把最初的第 l 堆到第 r 堆合并成一堆,状态方程式:
F [ l , r ] = min l ≤ k < r { F [ l , k ] + F [ k + 1 , r ] + ∑ i = l r A [ i ] F[l, r] = \min_{l{\leq}k<r} \{F[l, k] +F[k + 1, r] + \sum_{i = l}^{r}A[i] F[l,r]=l≤k<rmin{
F[l,k]+F[k+1,r]+i=l∑rA[i]
初值: ∀ \forall