• Codeforces 149D Coloring Brackets(树型DP)


    题目链接 Coloring Brackets

    考虑树型DP。(我参考了Q巨的代码还是略不理解……)

    首先在序列的最外面加一对括号。预处理出DFS树。

    每个点有9中状态。假设0位不涂色,1为涂红色,2为涂蓝色。

    0:0 0

    1:0 1

    2:0 2

    3:1 0

    4:1 1

    5:1 2

    6:2 0

    7:2 1

    8:2 2

    其中1、2、3、6为有效的状态。

    DP的时候如果当前括号下没有子括号那么这个状态方案数为1。

    先处理出第一对括号。然后处理接下来的括号。

    拼接的时候如果出现()() 中间两个括号同时染色并且颜色相同那么该状态不合法,跳过。

    转移的时候滚动一下。

    如果当前节点不是根的话那么最后处理的时候只保留合法的状态。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define LL long long
     6 
     7 const int valid[4] = {1,2,3,6};
     8 const LL mod = 1000000007;
     9 const int root = 0;
    10 
    11 char s[705];
    12 vector <int> e[705];
    13 stack <int> stk;
    14 LL f[705][9];
    15 int n, ret, tot;
    16 
    17 void dfs(int u){
    18     f[u][0] = 1;
    19     LL tmp[9];
    20     for (int i = 0, flag = 0; i < (int)e[u].size(); i++){
    21         int v = e[u][i];
    22         dfs(v);
    23         if (!flag){
    24             for (int tk = (f[u][0] = 0); tk < 4; ++tk){
    25                 int k = valid[tk];
    26                 f[u][k] = f[v][k];
    27             }
    28 
    29             flag = 1;
    30         }
    31 
    32         else{
    33             for (int j = 0; j < 9; ++j) tmp[j] = 0;
    34             for (int j = 0; j < 9; ++j)
    35                 for (int tk = 0; tk < 4; ++tk){
    36                     int k = valid[tk];
    37                     int cl[2] = {j / 3, j % 3}, cr[2] = {k / 3, k % 3};
    38                     if (cl[1] > 0 && cr[0] > 0 && cl[1] == cr[0]) continue;
    39                     int p = cl[0] * 3 + cr[1];
    40                     (tmp[p] += 1LL * f[u][j] * f[v][k]) %= mod;
    41                 }
    42 
    43             for (int j = 0; j < 9; ++j) f[u][j] = tmp[j];
    44         }
    45     }
    46 
    47     if (u != root){
    48         for (int j = 0; j < 9; ++j) tmp[j] = 0;
    49         for (int j = 0; j < 9; ++j)
    50             for (int tk = 0; tk < 4; ++tk){
    51                 int k = valid[tk];
    52                 int ci[2] = {j / 3, j % 3}, co[2] = {k / 3, k % 3};
    53                 if ((ci[0] > 0 && co[0] > 0 && ci[0] == co[0])
    54                 || (ci[1] > 0 && co[1] > 0 && ci[1] == co[1])) continue;
    55                 (tmp[k] +=f[u][j]) %= mod;
    56             }
    57         for (int j = 0; j < 9; ++j) f[u][j] = tmp[j];
    58     }
    59 }
    60 
    61 
    62 int main(){
    63 
    64     scanf("%s", s + 1);
    65     n = strlen(s + 1); tot = 0;
    66     s[0] = '(', s[n + 1] = ')';
    67     for (int i = 0; s[i]; ++i){
    68         if (s[i] == '('){
    69             if (tot) e[stk.top()].push_back(tot);
    70             stk.push(tot++);
    71         }
    72 
    73         else stk.pop();
    74     }
    75 
    76     dfs(root);
    77     ret = 0;
    78     for (int i = 0; i < 9; ++i) (ret += f[root][i]) %= mod;
    79     return 0 * printf("%d
    ", ret);
    80 }
  • 相关阅读:
    html中#include file的使用方法
    【leetcode】Next Permutation
    diameter
    android listview综合使用演示样例_结合数据库操作和listitem单击长按等事件处理
    【剑指offer】链表倒数第k个节点
    【经典面试题】实现平方根函数sqrt
    对CAB文件进行数字签名
    实习面试总结
    从队列、二叉树到优先队列
    句子的理解
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/6776110.html
Copyright © 2020-2023  润新知