"蔚来杯"2022牛客暑期多校训练营2 K Link with Bracket Sequence I
作者:互联网
K Link with Bracket Sequence I
题目大意:给定一个长度为\(n\)的括号序列\(a\),\(a\)是一个长度为\(m\)的合法括号序列\(b\)的子序列,求\(b\)的方案数
(\(mod\ 10^9+7,1<=n<=m<=200\) )
解题思路:考虑类似最长公共子序列的动态规划,加上括号序列需要合法的限制
\[dp[i][j][k]:=b的前i个最多匹配a的前j个,剩下k个左括号未匹配的方案数 \]定义状态:
\[a_{j+1}==')'\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j][k+1]\\ a_{j+1}=='('\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j+1][k+1] \]状态转移:
\(b\)多放一个左括号
\[a_{j+1}=='('\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j][k-1]\\ a_{j+1}==')'\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j+1][k-1] \]\(b\)多放一个右括号
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
const int N = 210, MOD = 1e9 + 7;
int dp[N][N][N];
char a[N];
void work() {
int n,m;
cin>>n>>m>>a+1;
memset(dp,0,sizeof dp);
dp[0][0][0]=1;
rep(i,0,m-1){
rep(j,0,min(i,n)){
rep(k,0,i){
// '('
if(a[j+1]=='(') dp[i+1][j+1][k+1]=(dp[i+1][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) continue;
if(a[j+1]==')') dp[i+1][j+1][k-1]=(dp[i+1][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][0]<<endl;
}
signed main() {
int test=1;
cin >> test;
while (test--)
work();
return 0;
}
标签:Sequence,蔚来,rep,多校,括号,Longrightarrow,longrightarrow,dp,MOD 来源: https://www.cnblogs.com/xhy666/p/16519344.html