大连赛区现场赛的E题。经典的简单DP。
设状态f[i][j]表示到达第i位以j结尾的方案数,则状态转移方程为:
如果为‘D’ 或者 ‘?’ 则:f[i][j] += sum(f[i-1][k]), j<=k<i
如果为'I'或者‘?’, 则:f[i][j] += sum(f[i-1][k]), 1<=k<j
最后统计一下就好了,这是个O(n^3)的算法,很显然地用部分和的思想优化一下就变成了O(n^2)的了。
PS:十分膜拜watashi大神的报告中的STL写法,太强大了.....
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#define Maxn 1010
using namespace std;
const int mod = 1000000007;
string s;
int f[Maxn][Maxn], n, ans;
int sum[Maxn][Maxn];
int main()
{
while (getline(cin, s))
{
memset(f, 0, sizeof(f));
memset(sum, 0, sizeof(sum));
f[0][0] = 1;
n = s.length();
for (int i=1; i<=n; i++) sum[0][i] = 1;
for (int i=1; i<=n; i++)
{
for (int j=1; j<=i+1; j++)
{
if (s[i-1] == 'I' || s[i-1] == '?')
{
f[i][j] += sum[i-1][j-1];
}
if (s[i-1] == 'D' || s[i-1] == '?')
{
f[i][j] += (sum[i-1][i] - sum[i-1][j-1]);
f[i][j] = (f[i][j] + mod) % mod;
}
sum[i][j] = (sum[i][j-1] + f[i][j]) % mod;
}
}
ans = 0;
for (int i=0; i<=n+1; i++) ans = (ans + f[n][i]) % mod;
cout <<ans <<endl;
}
return 0;
}