• Link with Bracket Sequence I(DP)


    题意

    给定一个长度为\(n\)的括号序列\(a\)(不一定是合法的)。

    现在要使用\(a\)构造一个长度为\(m\)的合法括号序列\(b\),其中\(a\)\(b\)的子序列(不一定连续)

    求方案数。

    题目链接:https://ac.nowcoder.com/acm/contest/33187/K

    数据范围

    \(1 \leq n \leq m \leq 200\)

    思路

    这道题很容易想到使用DP,并且通过时间复杂度推算,应该为三维DP。

    定义\(f(i, j, k)\)表示答案串已经有\(i\)个字符,括号序列\(a\)中的前\(j\)个字符是答案串的子序列,左括号比右括号数量多\(k\)的方案数。

    下面考虑转移方程。考虑答案串下一个要放的括号,即第\(i+1\)个字符。

    • 如果放左括号,如果\(a\)的第\(j+1\)个字符为左括号,那么就能够匹配上,则\(f(i+1,j+1,k+1) = f(i+1,j+1,k+1)+f(i,j,k)\)
    • 如果放左括号,如果\(a\)的第\(j+1\)个字符不为左括号,那么不能匹配,则\(f(i+1,j,k+1) = f(i+1,j,k+1)+f(i,j,k)\)
    • 如果放右括号,如果\(a\)的第\(j+1\)个字符为右括号,那么就能够匹配上,则\(f(i+1,j+1,k-1) = f(i+1,j+1,k-1)+f(i,j,k)\)
    • 如果放右括号,如果\(a\)的第\(j+1\)个字符不为右括号,那么不能匹配,则\(f(i+1,j,k-1) = f(i+1,j,k-1)+f(i,j,k)\)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 210, mod = 1e9 + 7;
    
    int n, m;
    char s[N];
    ll f[N][N][N];
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T --) {
            scanf("%d%d", &n, &m);
            scanf("%s", s + 1);
            for(int i = 0; i <= m; i ++) {
                for(int j = 0; j <= n; j ++) {
                    for(int k = 0; k <= m; k ++) {
                        f[i][j][k] = 0;
                    }
                }
            }
            f[0][0][0] = 1;
            for(int i = 0; i < m; i ++) {
                for(int j = 0; j <= min(i, n); j ++) {
                    for(int k = 0; k <= i; k ++) {
                        if(k < m && (j == n || s[j + 1] != '(')) {
                            f[i + 1][j][k + 1] = (f[i + 1][j][k + 1] + f[i][j][k]) % mod;
                        }
                        if(k < m && j < n && s[j + 1] == '(') {
                            f[i + 1][j + 1][k + 1] = (f[i + 1][j + 1][k + 1] + f[i][j][k]) % mod;
                        }
                        if(k && (j == n || s[j + 1] != ')')) {
                            f[i + 1][j][k - 1] = (f[i + 1][j][k - 1] + f[i][j][k]) % mod;
                        }
                        if(k < m && j < n && s[j + 1] == ')') {
                            f[i + 1][j + 1][k - 1] = (f[i + 1][j + 1][k - 1] + f[i][j][k]) % mod;
                        }
                    }
                }
            }
            printf("%lld\n", f[m][n][0]);
        }
        return 0;
    }
    
  • 相关阅读:
    css backgroud属性与雪碧技术
    css margin 外边距塌陷问题
    css 浮动元素与清除浮动
    css 盒模型的概念与使用
    七年iOS架构师教你如何一举拿下35K的Offer,(附面试技巧)
    iOS开发者月薪想要突破30K,需要经历+提升些什么?
    月薪 8K 与30K的程序员 区别到底在哪里?
    那些月薪35K以上的iOS开发者 都掌握了什么技能?
    从事 iOS 开发8年的面经——送给准备跳槽的你!
    想进BAT大厂的 iOS程序员,看完这个你还觉得Offer难拿吗???
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16606876.html
Copyright © 2020-2023  润新知