大连赛区现场赛的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; }