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;
}