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;
}
posted @ 2022-08-19 23:10  pbc的成长之路  阅读(22)  评论(0编辑  收藏  举报