Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)

题意:给你一组括号序列,让你进行染色,对于每个括号,有无色,红色,蓝色三种方案。染色需要满足这样的条件:互相匹配的括号,有且只有一个有颜色,相邻的括号不能颜色相同(可以同为无色),问合法的染色方案数(答案%1e9+7)

分析:根据题意能够看出是区间DP,并且状态转移的时候,依赖于左右两端的颜色,所以我们用dp[i][j][x][y]表示i到j的区间内左端颜色为x,右端颜色为y的方案数。

区间[i,j]可以由两种情况得到,一种是str[i],str[j]匹配,产生新的相匹配的括号,考虑在只有一端染色的情况下,由[i+1][j-1]的状态转移得到

二是由已经匹配好的两个区间得到,这里,我们可以先用栈预处理出,括号的匹配对应关系,这样就能找到匹配好的区间位置。

代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <functional>
#include  <map>
#include <vector>
#include <stack>
using namespace std;
#define INF 100000000
typedef long long LL;
stack<int>S;
const int MOD=1e9+7;
LL dp[710][710][3][3];
LL to[710];
char str[710];
int main()
{
    scanf("%s",str+1);
    int len=strlen(str+1);
    for(int i=1;i<=len;i++)
    {
        if(str[i]==‘(‘)
        S.push(i);
        else
        {
           int x=S.top();
           to[i]=x;
           to[x]=i;
           S.pop();
        }
    }
    for(int i=1;i<=len-1;i++)
    {
       if(str[i]==‘(‘&&str[i+1]==‘)‘)
       {
         dp[i][i+1][1][0]=1;
         dp[i][i+1][2][0]=1;
         dp[i][i+1][0][1]=1;
         dp[i][i+1][0][2]=1;
       }
    }

    for(int l=3;l<=len-1;l+=2)
        for(int i=1;i<=len-l;i++)
    {
        int j=i+l;
        if(str[i]==‘(‘&&str[j]==‘)‘)
        {
            dp[i][j][1][0]+=(dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1]+dp[i+1][j-1][2][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]);
            dp[i][j][1][0]%=MOD;

            dp[i][j][2][0]+=(dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][1][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]);
            dp[i][j][2][0]%=MOD;

            dp[i][j][0][1]+=(dp[i+1][j-1][0][2]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]);
            dp[i][j][0][1]%=MOD;

            dp[i][j][0][2]+=(dp[i+1][j-1][0][1]+dp[i+1][j-1][1][1]+dp[i+1][j-1][2][1]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]);
            dp[i][j][0][2]%=MOD;
        }
           int k=to[i];
            for(int x=0;x<3;x++)
                for(int y=0;y<3;y++)
            {
                  LL res=0;
                  for(int q1=0;q1<3;q1++)
                     for(int q2=0;q2<3;q2++)
                  {
                      if(q1==q2&&q1!=0)continue;
                      res=(res+dp[i][k][x][q1]*dp[k+1][j][q2][y])%MOD;
                  }
                 dp[i][j][x][y]=max(dp[i][j][x][y],res);
            }
    }

     LL ans=0;
    for(int i=0;i<=2;i++)
     for(int j=0;j<=2;j++)
    {
        ans+=dp[1][len][i][j];
    }
    printf("%lld\n",ans%MOD);
    return 0;
}

原文地址:https://www.cnblogs.com/a249189046/p/9668200.html

时间: 2024-10-11 01:16:10

Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)的相关文章

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #455 (Div. 2) C. Python Indentation dp递推

Codeforces Round #455 (Div. 2) C. Python Indentation 题意:python 里面,给出 n 个 for 循环或陈述语句,'f' 里面必须要有语句.按 python 缩进的方式组合成合法的程序,问有多少种可能方案. tags: dp dp[i][j] 表示第 i 个语句缩进为 j 时的可能方案数, 转移: 1] 如果第 i 个是 'f' , 则第 i+1 个肯定要比第 i 个多缩进一个单位,即 dp[i+1][j] = dp[i][j]. 2]如果

CF149D. Coloring Brackets[区间DP !]

不知道为什么居中了,先把代码放这 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=705,MOD=1e9+7; char s[N]; long long n,f[N][N][5][5]; int st[N],top=0,m[N]; void match(){ for(int i=1;i<=

codeferces 149D Coloring Brackets 区间dp

http://codeforces.com/problemset/problem/149/D 题目大致意思是给你一串字符串,只有小括号,并且已经符合括号匹配规则,现在要给这些括号涂色,给出一些涂色规则,求涂色的方案数. 1: 括号要么不被涂色,要么被涂成蓝色,要么被涂成红色. 2:两个相互匹配的括号有且仅有一个被涂色. 3:相邻两个括号不可以有相同颜色. 这里当然也是想到对区 [l, r] 间进行dp,但是这里对颜色有依赖关系,所以还需要记入 l 和 r 颜色的状态,一开始打算只用一维记录两个点

Codeforces Round #362 (Div. 1) B. Puzzles 树形dp,概率

题目链接: http://codeforces.com/problemset/problem/696/B 题意: 一个树,dfs遍历子树的顺序是随机的.所对应的子树的dfs序也会不同.输出每个节点的dfs序的期望 思路: http://www.cnblogs.com/01world/p/5795498.html 假设四个子节点为A,B,C,D,因为排列等可能,所以A在B前面的概率跟A在B后面的概率相等,C和D对于A而言一样.所以遍历A的时间期望就是( t(B) + t(C) + t(D) )/2

Codeforces Round #304 (Div. 2)——D素数筛+dp——Soldier and Number Game

Two soldiers are playing a game. At the beginning first of them chooses a positive integer n and gives it to the second soldier. Then the second one tries to make maximum possible number of rounds. Each round consists of choosing a positive integer x

Codeforces Round #282 Div.1 B Obsessive String --DP

题意: 给两个串S,T,问能找出多少的S的(a1,b1)(a2,b2)..(ak,bk),使Sa1---Sb1,...Sak---Sbk都包含子串T,其中k>=1,且(a1,b1)...(ak,bk)互不相交. 比如S = "abacaba",T="aba", 当k=1时,(0,6)满足,还有其他只包含一个aba串的也满足,k-2时,(0,2)(3,6)满足,(0,2)(4,6)也满足,(0,3)(4,6)也满足,所以总共有12种. 解法:dp.先用kmp找出