HDU-4055:Number String

链接:HDU-4055:Number String

题意:给你一个字符串s,s[i] = 'D'表示排列中a[i] > a[i+1],s[i] = 'I'表示排列中a[i] < a[i+1],s[i]  = '?' 表示无限制。

题解:dp[i][j]表示前i个满足字符串条件的结尾为j的 i 的排列。

如果s[i - 1]是' I ',那么dp[i][j] = dp[i-1][1] + dp[i-1][2] + .. + dp[i-1][j-1]

如果s[i - 1]是‘D’,那么dp[i][j] = dp[i-1][j] + dp[i-1][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]了。

#include <bits/stdc++.h>
using namespace std;

const int mod = 1000000007;
const int maxn = 1e3 + 10;
char s[maxn];
long long dp[maxn][maxn];   //前缀和

int main()
{
    while(scanf("%s", s) != EOF){
        int n = strlen(s);

        dp[0][1] = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= i + 1; j++){
                dp[i][j] = dp[i][j-1];      //前缀和累加
                if(s[i-1] != 'I') dp[i][j] += dp[i-1][i] - dp[i-1][j-1] + mod;
                if(s[i-1] != 'D') dp[i][j] += dp[i-1][j-1];
                dp[i][j] %= mod;
            }
        }

        printf("%lld\n", dp[n][n+1]);
    }

    return 0;
}

 

posted @ 2018-07-24 17:22  鬼沐冢  阅读(172)  评论(0编辑  收藏  举报