其他分享
首页 > 其他分享> > "蔚来杯"2022牛客暑期多校训练营2 K Link with Bracket Sequence I

"蔚来杯"2022牛客暑期多校训练营2 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个左括号未匹配的方案数 \]

状态转移:

\(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\)多放一个右括号

\[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] \]

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