区间动态规划

目录

一.区间dp简介

二.模板代码

三.典型例题

(1)P4170 [CQOI2007] 涂色 - 洛谷

三.总结


一.区间dp简介

区间dp:就是对于区间的一种动态规划,它将问题划分为若干个子区间,并通过定义状态和状态转移方程来求解每个子区间的最优解,最终得到整个区间的最优解。

对于某个区间,它的合并方式可能有很多种,我们需要去枚举所有的方式,通常是去枚举区间的分割点,找到最优的方式(一般是找最少消耗)。

例如:对于区间【i,j】,它的合并方式有很多种,可以是【i,i+1】和【i+2,j】也可以是【i,k】和【k+1,j】(其中i <= k < j)

区间动态规划_第1张图片

二.模板代码

//区间dp模板
//时间复杂度较高,o(n^3) 
//1.枚举区间长度
for(int len=2;len<=n;len++)
{
	//2.枚举左端点
	for(int i=1;len+i-1<=n;i++)
	{
		int j=len+i-1;
		//3.枚举右端点 
		for(int k=1;k

三.典型例题

(1)P4170 [CQOI2007] 涂色 - 洛谷

题目大意:

输入五个格子,代表目标格子。格子初始是空白的,一次涂色只能涂连续的格子,后一次涂色能够覆盖前一次的涂色,求要涂成目标格子颜色,最少得涂多少次。

思路:(下标从1开始)

我们注意到,题目需要求最小值,且数据范围较小,可以优先考虑区间dp。

通过枚举格子数来寻找规律:

1个格子情况                   输入                         输出

                                         A                             1

两个格子情况    (*)          AA                            1                A+A     ==>1+1=2

                                        AB                            2               A+B     ==>1+1=2

三个格子情况    (*)        AAA                            1               A+AA/AA+A    ==>min(1+1/1+1)=2

                                      ABC                           3              A+BC/AB+A    ==>min(1+2/2+1)=3

                                     BAA                             2              B+AA/BA+A    ==>min(1+1/2+1)=2

                          (*)       ABA                             2              A+BA/AB+A    ==>min(1+2/2+1)=3

                                     AAB                             2             A+AB/AA+B    ==>min(1+2/1+1)=2

总结得出规律:

当目标串中首尾字符相同,我们可以将第一个字符或最后一个字符去掉,取更小的情况。

其他情况使用区间dp取min即可。

1.状态表示 dp[i][j]  表示区间【i,j】满足条件(目标子串)的最少涂色次数。

2.状态计算:

当目标串中首尾字符相同,我们可以将第一个字符或最后一个字符去掉,取更小的情况。

其他情况使用区间dp取min即可。(代码解释见代码)

3.初始值:初始化dp数组为0x3f3f3f3f,dp[i][i]=1(区间长度为1时只涂1次)

最后输出dp[1][n]

参考代码:

//涂色
#include
#include
#include
using namespace std;
const int N=55;
char a[N];
int dp[N][N];

int main()
{
	scanf("%s",a+1);
	int n=strlen(a+1);
    //重点:!(要求最小值,初始化为无穷大)
    memset(dp,0x3f,sizeof(dp));
	
	//初始化数组
	for(int i=1;i<=n;i++)  dp[i][i]=1;
	
	for(int len=2;len<=n;len++)
	{
		for(int i=1;len+i-1<=n;i++)
		{
			int j=len+i-1;
			if(a[i]==a[j]) dp[i][j]=min(dp[i+1][j],dp[i][j-1]);
			else
			{
				for(int k=1;k

三.总结

区间dp的数据范围一般比较小,做题时可以由数据范围找突破口,其次就是模板的运用了,这类问题一般不难,难点在于状态转移方程的确定和其他的规律发现。

你可能感兴趣的:(动态规划,算法)