题解:CF629C Famil Door and Brackets
CF629C Famil Door and Brackets
题意
给定一长度为 \(m\) 且包含 ( 及 ) 的字符串 \(S\) ,要求构造两个只包含 ( 及 ) 的字符串 \(P,Q\) ,使得 \(P+S+Q\) 满足以下条件:
-
\(P+S+Q\) 的长度为给出的 \(n\) 。
-
\(P+S+Q\) 中
(与)的数量相等。 -
对于 \(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)}\)
计算结果
-
枚举 \(P\) 的长度 \(i\) 。
-
枚举 \(P\) 中的
(与)之差,要求(与)之差满足对于 \(S\) 中任意位置前缀都满足(大于)数量。 -
则 \(Q\) 的长度为 \(n-m-i\) ,验证能否构造出 \(Q\) 使得 \(P+S+Q\) 满足所有条件。
-
若满足则通过 乘法原理 统计对于该长度的 \(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;
}
完结撒花!

浙公网安备 33010602011771号