Loading

题解:CF629C Famil Door and Brackets

CF629C Famil Door and Brackets

题意

给定一长度为 \(m\) 且包含 () 的字符串 \(S\) ,要求构造两个只包含 () 的字符串 \(P,Q\) ,使得 \(P+S+Q\) 满足以下条件:

  1. \(P+S+Q\) 的长度为给出的 \(n\)

  2. \(P+S+Q\)() 的数量相等。

  3. 对于 \(P+S+Q\) 中的任意位置的前缀满足 ( 的数量不小于 ) 的数量。

求满足构造条件的 \(P,Q\) 的方案总数,并输出其对 \(10^9+7\) 取余的值。

思路

题目中给出 \(n-m \le 2000\) 且只需求出结果,故想到使用 DP 进行求解。

预处理

预处理 \(S\) 串,求出在 \(P\) 中需要补齐 ( 的最小数量,使得 \(P+S\) 满足条件 \(3\)

动态规划

设状态 \(f(i,j)\) 表示为前 \(i\) 个字符中 () 之差为 \(j\) 的方案总数。

因为 \(0 \le n \le 2000\) 所以我们只需求出 \(2000\) 以内的所有情况的值即可。

对于状态转移有:

  • 起始为 \(f(0,0)=1\)

  • 转移方程为 \(\large{f(i,j)=f(i-1,j+1)+f(i-1,j-1)}\)

计算结果

  1. 枚举 \(P\) 的长度 \(i\)

  2. 枚举 \(P\) 中的 () 之差,要求 () 之差满足对于 \(S\) 中任意位置前缀都满足 ( 大于 ) 数量。

  3. \(Q\) 的长度为 \(n-m-i\) ,验证能否构造出 \(Q\) 使得 \(P+S+Q\) 满足所有条件。

  4. 若满足则通过 乘法原理 统计对于该长度的 \(P\) 的所有构造方案数量,并通过 加法原理 统计对所有方案进行求和。

更多详情请看代码。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9+7;
ll n, m, minn, ans, z, f[2005][2005];
string S;
int main() {
	cin >> n >> m >> S; //n表示需构造字符串长度, m为初始字符串长度
	for (int i = 0; i < (int)S.length(); i++) {
		S[i] == '(' ? z++ : z--; //对s中的前i个字符的括号抵消情况进行判断
		minn = min(z, minn); //求S中'('缺失最多的情况
	}
	f[0][0] = 1; //f[0][0]只有一种情况就是字符串为空
	for (int i = 1; i <= 2000; i++) { //枚举长度,依次增加
		f[i][0] = f[i - 1][1]; //(0-1)<0所以无需计算
		for (int  j = 1; j <= i; j++) //枚举'('与')'之差
			f[i][j] = (f[i - 1][j - 1] + f[i - 1][j + 1]) % mod;
	}
	for (int i = 0; i <= n - m; i++) //枚举P的长度,其中'n-m'指P和Q的总长度
		for (int  j = 0; j <= i; j++) //枚举在P中'('与')'的差
			if (j + minn >= 0 && j + z <= (n - m - i)) 
			/*使P中'('与')'的差能够满足补齐S中少的'(' 且 使构造的Q能使P+S+Q中'('')'数量相等,即Q的长度不小于P+S中'('与')'的差*/
				ans = (ans + (f[i][j] * f[n - m - i][j + z]) % mod) % mod;
	cout << ans << endl;
	return 0;
}

完结撒花!

posted @ 2024-07-10 14:36  Anins  阅读(30)  评论(0)    收藏  举报  来源