$$ \text{题意:给定一个括号序列,求插入若干个括号,将这个括号序列变成} \\ \text{长度为}2\times n\text{的括号序列的方案数} \\ \\ \text{一开始考虑阶段设置为当前要在原串第几个字符后面加字符,然后发现根本没法转移}.. \\ \text{然后考虑把阶段设置为,当前放置了几个字符} \\ \text{设}f\left( n,m,k \right) \text{表示当前已经放置完成了}n\text{个字符,使用掉了原串的前}m\text{个字符} \\ \text{已经放置好了的字符串中,左括号比右括号多}k\text{个} \\ \text{时候的方案数} \\ \text{首先是边界条件}f\left( \text{0,0,}0 \right) =1 \\ \text{因为空串只有一种方案} \\ \text{转移时,首先考虑当前位置是左括号还是右括号。} \\ \text{然后如果这时候可以使用原串中的字符来完成转移,那么要优先使用原串字符} \\ \text{除非原串的字符不能完成这次转移,再去考虑加入新的字符} \\ \text{左括号时:} \\ f\left( n,m,k \right) =f\left( n,m,k \right) +f\left( n-\text{1,}m-\text{1,}k-1 \right) \left( \text{原串第}m\text{位置为左括号} \right) \\ f\left( n,m,k \right) =f\left( n,m,k \right) +f\left( n-\text{1,}m,k-1 \right) \left( \text{原串第}m\text{位置不是左括号} \right) \\ \text{右括号时:} \\ f\left( n,m,k \right) =f\left( n,m,k \right) +f\left( n-\text{1,}m-\text{1,}k+1 \right) \left( \text{原串第}m\text{位置为右括号} \right) \\ f\left( n,m,k \right) =f\left( n,m,k \right) +f\left( n-\text{1,}m,k+1 \right) \left( \text{原串第}m\text{位置不是右括号} \right) \\ \text{最后答案放置了}2\times n\text{个字符,使用了原串的全部字符,左括号比右括号多0个的方案数} $$
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <inttypes.h>
#include <string>
#include <map>
#include <cstring>
#define debug(x) std::cout << #x << " = " << x << std::endl;
typedef long long int int_t;
using std::cin;
using std::endl;
using std::cout;
const int_t mod = 1000000007;
const int_t LARGE = 300;
char buff[LARGE + 10];
int_t val[LARGE + 1];
int_t prefix[LARGE + 1];
int_t dp[LARGE + 1][LARGE + 1][LARGE + 1];
int_t n;
int_t len;
void inc(int_t& x,int_t p) {
x = (x % mod + p + 2 * mod) % mod;
}
int main() {
freopen("regular.in","r",stdin);
freopen("regular.out","w",stdout);
cin >> n;
scanf("%s",buff + 1);
len = strlen(buff + 1);
for(int_t i = 1; i <= len; i++) {
if(buff[i] == '(') val[i] = 1;
else val[i] = -1;
prefix[i] = prefix[i - 1] + val[i];
}
dp[0][0][0] = 1;
for(int_t i = 1; i <= 2 * n; i++) {
for(int_t j = 0; j <= std::min(i,len); j++) {
for(int_t k = 0; k <= i; k++) {
//×óÀ¨ºÅ
if(val[j]==1&&k-1>=0&&j>0){
inc(dp[i][j][k],dp[i-1][j-1][k-1]);
} else{
if(k-1>=0)inc(dp[i][j][k],dp[i-1][j][k-1]);
}
//ÓÒÀ¨ºÅ
if(val[j]==-1&&j>0){
inc(dp[i][j][k],dp[i-1][j-1][k+1]);
} else{
inc(dp[i][j][k],dp[i-1][j][k+1]);
}
continue;
}
}
}
cout<<dp[2 * n][len][0]<<endl;
return 0;
}
发表回复