原题: FZU 2170 http://acm.fzu.edu.cn/problem.php?pid=2170
这题确实是当时没读懂题目,连样例都没想通,所以没做了,所以还是感觉这样散漫的做不好,有些题目明明很简单,却因为没看懂而放弃了,甚至去玩了,这样达不到太大的效果。
解法:
定义: dp[i][j]:前i个字母中有j个是属于第一个序列的标号方案种数。
则当遇到'B'时,因为要满足WB依次间歇出现,所以前面属于第一个序列的个数应该为奇数,即j&1时转移。当属于第二个序列的个数为奇数时((i-j)&1)也要转移,因为这个B有可能属于第二个序列。当遇到'W'时反之。
用滚动数组节省空间。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define Mod 1000000007
using namespace std;
#define N 6007 int dp[][N];
char ss[N]; int main()
{
int n,i,j;
int now;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%s",ss);
memset(dp,,sizeof(dp));
dp[][] = ;
for(i=,now=;i<*n;i++,now=-now)
{
memset(dp[now],,sizeof(dp[now]));
if(ss[i] == 'B')
{
for(j=;j<=n;j++)
{
if(j&)
dp[now][j+] = (dp[now][j+]+dp[i&][j])%Mod;
if((i-j)&)
dp[now][j] = (dp[now][j]+dp[i&][j])%Mod;
}
}
else
{
for(j=;j<=n;j++)
{
if((j&) == )
dp[now][j+] = (dp[now][j+]+dp[i&][j])%Mod;
if(((i-j)&) == )
dp[now][j] = (dp[now][j]+dp[i&][j])%Mod;
}
}
}
printf("%d\n",dp[][n]);
}
return ;
}