官方题解
2025-09-15 12:43:12
发布于:浙江
6阅读
0回复
0点赞
题目大意
求长度为 的括号序列 可能是多少个长度为 的合法括号序列 的子序列。
题目思路
读题时需要注意的一个点是括号序列 不一定是合法的,但求的括号序列 一定是要合法的。
我们可以将 (
看成权值为 ,将 )
看成权值为 ,那么一个合法的括号序列需要满足以下条件:
- 序列和为 。
- 最小前缀和为不小于 。
我们考虑用动态规划解决这个问题。
设 表示括号序列 中已经有 个字符,括号序列 的前 个字符是括号序列 的子序列,括号序列 的权值前缀和为 。
那么有以下四种转移:
- 位置为
(
,且 或(
,则 。 - 位置为
(
,且 且(
,则 。 - 位置为
)
,且 或)
,则 。 - 位置为
)
,且 且)
,则 。
时间复杂度 。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
const int mod = 1e9+7;
int dp[N][N][N];
void solve(){
int n,m;cin>>n>>m;
string s;cin>>s;s=' '+s;
for(int i=0;i<=m+1;i++){
for(int j=0;j<=n+1;j++){
for(int k=0;k<=m+1;k++){
dp[i][j][k]=0;
}
}
}
dp[0][0][0]=1;
for(int i=0;i<m;i++){
for(int j=0;j<=min(i,n);j++){
for(int k=0;k<=i;k++){
if(!dp[i][j][k]) continue;
if(k && (j==n || s[j+1]!=')')) (dp[i+1][j][k-1]+=dp[i][j][k])%=mod;
if(k<m && (j==n || s[j+1]!='(')) (dp[i+1][j][k+1]+=dp[i][j][k])%=mod;
if(k && j<n && s[j+1]==')') (dp[i+1][j+1][k-1]+=dp[i][j][k])%=mod;
if(k<m && j<n && s[j+1]=='(') (dp[i+1][j+1][k+1]+=dp[i][j][k])%=mod;
}
}
}
cout<<dp[m][n][0]<<endl;
}
int main(){
int T=1;cin>>T;
while(T--){
solve();
}
}
这里空空如也
有帮助,赞一个