DP经典好题。。。
题意简述:
给定一个字符串由'I' 'D' '?'组成,长度为n,表示1-n+1个数任意排列满足字符串给出的限定条件,I表示第i位到第i+1位是上升的,D表示是下降的,?表示都可以,问有多少种排列满足给出的条件,答案要%一个mod值1e9+7
思路浅析:
设dp[ i ] [ j ] 表示前 i 个满足字符串条件结尾为 j 的i的排列
若s[i] == 'I', dp[ i ] [ j ] = dp[ i - 1 ] [ j - 1 ] + dp[ i - 1 ] [ j - 2 ] +...+ dp[ i - 1 ] [ 1 ]
若s[i] == 'D', dp[ i ] [ j ] = dp [ i - 1 ] [ j ] + dp[ i ] [ j + 1 ] +...+ dp[ i - 1 ] [ i ]
若下一步是下降的,那么因为要令当前位为j,如果前面出现过j,就令前面的所有大于等于j的数+1,就能构造出新的排列了。比如
{1, 3, 5, 2, 4},要在第六位插入3,令 >= 3的数都+1,于是就构造出新的 排列{1, 4, 6, 2, 5, 3}。然后代码的话处理出前缀和sum[i][j],就不用dp[i][j]了
code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int N = 1010;
int sum[N][N];
char s[N];
main()
{
// freopen("in.txt", "r", stdin);
while (scanf("%s", s) != -1)
{
sum[0][1] = 1;
int n = strlen(s);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n + 1; j++)
{
sum[i][j] = sum[i][j - 1];
if (s[i - 1] != 'D')
sum[i][j] += sum[i - 1][j - 1];
if (s[i - 1] != 'I')
sum[i][j] += (sum[i - 1][i] - sum[i - 1][j - 1] + mod);
sum[i][j] %= mod;
}
std::cout << sum[n][n + 1] << '\n';
}
return 0;
}