HDU4055_Number String

题目告诉你在一个排列中,相邻两个数的大小关系。问你排列可能有多少种情况。

DP。

f[i][j]表示将i个数按照前面i-1个大小关系排列且最后一个数位j的排列数有多少个。

这样对于新加入的一个数i+1,我们直接枚举第i+1个数在所有的i+1个数为第几大即可。

注意加入sum数组,不然时间复杂度就是O(N^3)了。

注意不要每次取模,注意不需要long long。注意时间常数。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1010
#define M 1000000007
using namespace std;

int f[maxn][maxn],sum1[maxn],sum2[maxn];
char s[maxn];

int count(int x)
{
    if (x<M) return x;
    return x-M;
}

int main()
{
    while (scanf("%s",s+1)!=EOF)
    {
        memset(f,0,sizeof f);
        memset(sum1,0,sizeof sum1);
        memset(sum2,0,sizeof sum2);
        f[1][1]=1,sum1[1]=1,sum2[1]=1;
        for (int i=1; s[i]; i++)
        {
            for (int j=1; j<=i+1; j++)
            {
                if (s[i]=='?') f[i+1][j]=count(sum1[j-1]+sum2[j]);
                else if (s[i]=='I') f[i+1][j]=sum1[j-1];
                else if (s[i]=='D') f[i+1][j]=sum2[j];
            }
            sum1[1]=f[i+1][1];
            for (int j=2; j<=i+1; j++) sum1[j]=count(sum1[j-1]+f[i+1][j]);
            sum2[i+1]=f[i+1][i+1];
            for (int j=i; j>0; j--) sum2[j]=count(sum2[j+1]+f[i+1][j]);
        }
        int ans=0,n=strlen(s+1)+1;
        for (int i=1; i<=n; i++) ans=count(ans+f[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-11-22 17:09  092000  阅读(280)  评论(0编辑  收藏  举报