0
点赞
收藏
分享

微信扫一扫

“蔚来杯“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;
}


举报

相关推荐

0 条评论