zoukankan      html  css  js  c++  java
  • 区间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)这东西以后再学

  • 相关阅读:
    25条提高Visual Studio编码和调试效率的技巧
    难得的中文ASP.NET 5/MVC 6入门教程
    入门产品经理如何分析设计一个产品
    DNX/ASP.NET 5的xUnit入门向导
    打造理想的Windows 10 APP开发环境的5个步骤
    激励远程员工的5个高招
    Windows Live Writer技巧
    免费电子书:C#代码整洁之道
    JavaScript前端框架的思考
    利用Browser Link提高前端开发的生产力
  • 原文地址:https://www.cnblogs.com/ifmyt/p/9534387.html
Copyright © 2011-2022 走看看