天天看点

“蔚来杯“2022牛客暑期多校训练营2 K.[Link with Bracket Sequence I] 括号序列 DP

K.​​Link with Bracket Sequence I​​ (DP)

题目分析

给定长度为的括号序列(不保证合法性),求在此基础上生成的长度为括号序列的方案数。

设表示插入括号的数量为、使用的原来的序列中的括号数量为,左括号比右括号多时的方案数。那么最终答案为。那么考虑如何设计状态转移:

Code

#include <bits/stdc++.h>
#pragma gcc optimize(2)
#pragma g++ optimize(2)
// #define int long long
#define endl '\n'
using namespace std;

const int N = 2e5 + 10, mod = 1e9 + 7;
int dp[220][220][220];

inline void solve(){
    // memset(dp, 0, sizeof(dp));
    int m, n; cin >> n >> m;
    string s; cin >> s;
    // if(n & 1 || (m - n) & 1) { cout << 0 << endl; return; }
    dp[0][0][0]=1;
    for (int i = 0; i <= m - n; ++i)
    for (int j = 0; j <= n; ++j)
        for (int k = 0; k <= m; ++k){
            if (s[j] == '(' && j < n)
                dp[i][j + 1][k + 1] = (dp[i][j + 1][k + 1] + dp[i][j][k]) % mod;
            else
                dp[i + 1][j][k + 1] = (dp[i + 1][j][k + 1] + dp[i][j][k]) % mod;
            if (k > 0){
                if (s[j] == ')' && j < n)
                    dp[i][j + 1][k - 1] = (dp[i][j + 1][k - 1] + dp[i][j][k]) % mod;
                else
                    dp[i + 1][j][k - 1] = (dp[i + 1][j][k - 1] + dp[i][j][k]) % mod;
            }
        }
    cout << dp[m - n][n][0] << endl;
    for(int i = 0; i <= m + 2; i++)
        for(int j = 0; j <= n + 2; j++)
            for(int k = 0; k <= m + 2; k++) dp[i][j][k] = 0;
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int t = 1; cin >> t;
    while(t--) solve();
    return 0;
}      

继续阅读