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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理