括号序列模型及解法
>Codeforces314E
◦给定一个长度为n的仅包含左右括号和问号的字符串,将问号变成左括号
或右括号使得该括号序列合法,求方案总数。
◦例如(())与()()都是合法的括号序列。
◦ n<=3000。
>Solution
◦括号序列问题,往往就是把左括号看成+1,右括号看成-1,我们只需要
保证任意一个前缀大于等于0,且总和为0,就代表是个合法括号序列了。
◦令dp[i][j]表示当前到第i个字符,现在的前缀和
◦那么分三种情况考虑。
◦若第i+1个字符是左括号,则能转移到dp[i+1][j+1]。
◦若第i+1个字符是右括号,则能转移到dp[i+1][j-1]。
◦若第i+1个字符是问号,则能转移到dp[i+1][j-1]与dp[i+1][j+1]。
◦最终dp[n][0]就是方案总数啦。
◦时间复杂度为O(n^2)。
U86873 小Y的精灵国机房之旅
题解
括号序列模型唉!
所以就可以套用上面的式子啦
把Y看做左括号,H看做右括号,C看做问号
准备AC
#include<iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=10010,mod=1e9+7; int n; char a[maxn]; int f[3000][3000]; int main() { n=read(); scanf("%s",a+1); f[0][0]=1; for(int i=1;i<=n;i++){ if(a[i]=='Y'){ f[i][0]=0; for(int j=1;j<=i;j++){ f[i][j]=f[i-1][j-1]; } } if(a[i]=='H'){ for(int j=0;j<i;j++){ f[i][j]=f[i-1][j+1]; } f[i][i]=0; } if(a[i]=='C'){ for(int j=1;j<i;j++){ f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%mod; } f[i][0]=f[i-1][1]; f[i][i]=f[i-1][i-1]; } } printf("%d ",f[n][0]%mod); return 0; }
然后发现不对劲。。。。。
二维数组一定会炸。。。。
那就。。。循环队列!
我们发现每次到新的一个 i ,它只和 i-1 有关,所以 i-1 用过一次就可以销毁了,不然也是占空间
可以像这样&1来实现循环利用
代码
#include<iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=10010,mod=1e9+7; int n; char a[maxn]; int f[3][maxn]; int main() { n=read(); scanf("%s",a+1); memset(f,0,sizeof(f)); f[0][0]=1; for(int i=1;i<=n;i++){ if(a[i]=='Y'){ f[i&1][0]=0; for(int j=1;j<=i;j++){ f[i&1][j]=f[(i-1)&1][j-1]; } } if(a[i]=='H'){ for(int j=0;j<i;j++){ f[i&1][j]=f[(i-1)&1][j+1]; } f[i&1][i]=0; } if(a[i]=='C'){ f[i&1][0]=f[(i-1)&1][1]; for(int j=1;j<i;j++){ f[i&1][j]=(f[(i-1)&1][j-1]+f[(i-1)&1][j+1])%mod; } f[i&1][i]=f[(i-1)&1][i-1]; } } printf("%d ",f[n&1][0]%mod); return 0; }