区间dp学习笔记

怎么办,膜你赛要挂惨了,下午我还在学区间(dp)!

不管怎么样,计划不能打乱(4)(4)。。

区间dp

模板

为啥我一开始就先弄模板呢?因为这东西看模板就能看懂。。。

for(int i=2;i<=len;i++)//枚举区间长度
{
	for(int l=1,r=l+len-1;r<=n;l++,r++)//枚举左端点和右端点
	{
		//以下你可以搞一下事情
		for(int k=l;k<r;k++)
		{
			//以下你还可以搞一下事情
			dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]); 
		 } 
	}
}

以上就是区间dp的大体模板,至于为啥,感性理解一下就好了

例题

石子合并加强版

为啥我一开始就弄加强版呢?因为普通版就在加强版里面哇(qwq)
传送门
这道题目是说一个环形操场,然后合并成一堆的最大值最小值
注意加粗的字体,环形操场?
好吧,这就是一个环形(dp),通常的就是复制一遍,断环为链,别问我为啥是这样
然后就是状态转移方程。(dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]))(dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]))
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N = 1000;
int n,a[1000],dpmax[N][N],dpmin[N][N],sum[N];
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]),a[i+n]=a[i];
    for(int i=1; i<=n*2; i++)
        sum[i]=sum[i-1]+a[i];
    memset(dpmin,0x3f,sizeof(dpmin));
    for(int i=1; i<=n*2; i++)dpmin[i][i]=0;
    for(int len=2; len<=n; len++)
    {
        for(int l=1,r=len+l-1; r<=n*2; l++,r++)
        {
            for(int k=l; k<r; k++)
                dpmax[l][r]=max(dpmax[l][r],dpmax[l][k]+dpmax[k+1][r]+sum[r]-sum[l-1])
                            ,dpmin[l][r]=min(dpmin[l][r],dpmin[l][k]+dpmin[k+1][r]+sum[r]-sum[l-1]);
        }
    }
    int maxn=0,minn=0x7fffffff;
    for(int i=1; i<=n; i++)minn=min(minn,dpmin[i][i+n-1]),maxn=max(maxn,dpmax[i][i+n-1]);
    cout<<minn<<endl<<maxn;
}

括号匹配问题

传送门

这道题也是(dp)问题,不算特别的裸,毕竟用到了字符串。

因为我们要判断括号的合法性,所以我们在枚举左端点和右端点的时候,只要合法,括号序列就(+2),也就是(dp[l][r]=dp[l+1][r-1]+2)这个看不懂的人不多吧

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
char s[255];
int dp[300][300];
int main()
{
	while(1)
	{
		cin >> s+1;
		if(s[1]=='e')break;
		memset(dp,0,sizeof(dp));
		int len=strlen(s+1);
		for(int i=2; i<=len; i++)
		{
			for(int l=1,r=i+l-1; r<=len; l++,r++)
			{
				if((s[l]=='('&&s[r]==')')||(s[l]=='['&&s[r]==']'))
					dp[l][r]=dp[l+1][r-1]+2;
				for(int k=l; k<r; k++)
				{
					dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);
				}
			}
		}
		printf("%d
",dp[1][len]);
	}
}

关于区间(dp)还有一个东西叫做四边形不等式优化,(emmm)这东西以后再学

原文地址:https://www.cnblogs.com/ifmyt/p/9534387.html