• 【DP】【区间DP】D. Coloring Brackets


    D. Coloring Brackets

    image

    预处理

    由于栈的特性,我们可以储存左括号和读取到刚刚读到的左括号,并当读取到右括号时,我们可以将最近的左括号提取出来并做一个匹配处理。

    DP的设置

    DP数组的设置,dp[l][r][color1][color2]表示的是l位置是color1和r位置是color2的方案数。

    第一种情况,当l和r是匹配的关系,即左括号对上了对应的右括号,那么我们就可以以根据题目的条件提前确定color1和color2的内容,就是一者没有上任何的颜色,另一者上了蓝色或者红色,而这一共有四种可能,因而我们要考虑四个状态的转移,而由于l和r是先确定的,我们可以进而去考虑l+1和r-1所构成的区间,并注意题目给的的限制条件(相邻的括号不能上同样的颜色)

    第二种情况,不是第一种情况的情况。

    由于提前处理了,可以很方便得到l所对应上的r,因而我们可以先处理一部分已经完成匹配的括号对,然后再假装从这个括号对后面的部分,注意这个设计要保证是没有任何疏漏,不能放过区间上任何一个括号。因而,我们可以这么分,l到l所对应的r的部分,l所对应的r的部分再到区间末端这两个部分(l所对应的r的部分再到区间末端这两个部分的这一部分,由于dfs的特性,会被相同不断操作,从而保障了区间内全部的点全部被操作一遍)。

    对了,上述这些只是一种思路或者说是dp的一种大体的框架。

    我们还要考虑到边界的书写,

    我们的做法是不断将这些区间进行压缩,压缩的最终结果肯定会发生的情况是两个括号直接黏在一起,而这也会对应第一种情况内的那四种方案,换句话说这种边界的处理相当于是第一种情况的特例。

    代码

    #include <bits/stdc++.h>
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define pi acos(-1.0)
    #define PII pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define ull unsigned long long
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define MAX 1000005
    #define MOD 1000000007
    #define INF 0x3f3f3f3f
    #define lowbit(x) (x&-x)
    using namespace std;
    int n,m;
    int dp[701][701][3][3],link[701];
    stack<int > pos;
    void dfs(int l,int r)
    {
    	if(r==l+1)
    	{
    		dp[l][r][0][2]=1;
    		dp[l][r][0][1]=1;
    		dp[l][r][2][0]=1;
    		dp[l][r][1][0]=1;
    	}   
    	else if(link[l]==r)
    	{
    		dfs(l+1,r-1);
            repd(p,0,2)
    		    repd(q,0,2)
    			{
    			    if(q!=2) dp[l][r][0][2] = (dp[l][r][0][2]+dp[l+1][r-1][p][q])%MOD;   	
    		        if(q!=1) dp[l][r][0][1] = (dp[l][r][0][1]+dp[l+1][r-1][p][q])%MOD; 
    		        if(p!=2) dp[l][r][2][0] = (dp[l][r][2][0]+dp[l+1][r-1][p][q])%MOD; 
    		        if(p!=1) dp[l][r][1][0] = (dp[l][r][1][0]+dp[l+1][r-1][p][q])%MOD; 
    			}	    
    	}
    	else
    	{
    		dfs(l,link[l]);dfs(link[l]+1,r);
    		ll res=0;
    		repd(i,0,2)
    		    repd(j,0,2)
    		        repd(p,0,2)
    		            repd(q,0,2)
    		                if( !((p==q)&&(p==1||p==2)) ) 
    		                  dp[l][r][i][j] = (dp[l][r][i][j]+dp[l][ link[l] ][i][p]*dp[ link[l] + 1 ][r][q][j])%MOD;
    	}
    }
    int main()
    {
    	MEM(dp,0);
    	string s;
    	cin>>s;
    	ll len = s.length(),ans=0;
    	//predo
    	rep(i,0,len)
    	{
    		if(s[i]=='(')
    	       pos.push(i+1);
    	    else
    	    {
    	    	link[ pos.top() ] = i+1;
    			link[ i+1 ] = pos.top();
    			pos.pop(); 
    		}
    	}
    	
    	dfs(1,len);
    	repd(i,0,2)
    	    repd(j,0,2)
    	        ans=(ans+dp[1][len][i][j])%MOD;
    	cout<<ans;
        return 0;
    }
    
    

    人生中第一道紫题(好像是)

    其他

    • Each bracket is either not colored any color, or is colored red, or is colored blue.

    either......or......是指列举出来的条件只有一个是成立的。

    colored + 颜色名,被染上某种颜色

    每一个括号要么被没涂上任何的颜色,要么上了红色,要么就是上了蓝色。


    • For any pair of matching brackets exactly one of them is colored. In other words, for any bracket the following is true: either it or the matching bracket that corresponds to it is colored.

    一对中的一个括号才有颜色。

    and vice versa 反之亦然

  • 相关阅读:
    关于在Eclipse中使用正则表达式替换的一点记录(使用正则表达式的分组)
    C#学习笔记(六):可空类型、匿名方法和迭代器
    C#学习笔记(五):泛型
    C#学习笔记(四):委托和事件
    C#学习笔记(三):值类型、引用类型及参数传递
    C#学习笔记(二):继承、接口和抽象类
    Unity3D之AssetBundle学习:Android上运行笔记
    js arguments 内置对象
    JS面向对象高级特性
    js 阻止事件冒泡 支持所有主流浏览器
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15195627.html
Copyright © 2020-2023  润新知