HDU 4055 Number String 计数DP

Number String HDU - 4055

定义一个只含 1 ∼ n 1\sim n 1n 的数字串 { a 1 , a 2 , ⋯   , a n } \{a_1,a_2,\cdots,a_n\} {a1,a2,,an} 的签名如下,假如当前大于前一位,则当前位记为 I I I,否则记为 D D D,比如:

the signature of the permutation {3,1,2,7,4,6,5} is “DIIDID”.

现在给一个长度为 n n n 的签名,问符合该签名的数字串有多少个?

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 i i i 个数,末尾是 j j j 对应的个数,按情况讨论(令 s [ i ] [ j ] = ∑ k = 1 j d p [ i ] [ k ] s[i][j]=\sum_{k=1}^jdp[i][k] s[i][j]=k=1jdp[i][k]):

(1) a [ i ] = ′ ? ′ a[i]='?' a[i]=?

d p [ i ] [ j ] = ∑ k = 1 i − 1 d p [ i − 1 ] [ k ] = s [ i − 1 ] [ i − 1 ] dp[i][j]=\sum_{k=1}^{i-1}dp[i-1][k]=s[i-1][i-1] dp[i][j]=k=1i1dp[i1][k]=s[i1][i1]

(2) a [ i ] = ′ I ′ a[i]='I' a[i]=I

d p [ i ] [ j ] = ∑ k = 1 j − 1 d p [ i − 1 ] [ k ] = s [ i − 1 ] [ j − 1 ] dp[i][j]=\sum_{k=1}^{j-1}dp[i-1][k]=s[i-1][j-1] dp[i][j]=k=1j1dp[i1][k]=s[i1][j1]

(3) a [ i ] = ′ D ′ a[i]='D' a[i]=D

d p [ i ] [ j ] = ∑ k = j i − 1 d p [ i − 1 ] [ k ] = s [ i − 1 ] [ i − 1 ] − s [ i − 1 ] [ j − 1 ] dp[i][j]=\sum_{k=j}^{i-1}dp[i-1][k]=s[i-1][i-1]-s[i-1][j-1] dp[i][j]=k=ji1dp[i1][k]=s[i1][i1]s[i1][j1]

代码如下:

#include
#include
#include
#define MAXN 1010
#define MOD 1000000007
using namespace std;
typedef long long ll;
char a[MAXN];
ll dp[MAXN][MAXN],s[MAXN][MAXN];
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    while(scanf(" %s ",a)!=EOF){
        int n=strlen(a)+1;
        dp[1][1]=s[1][1]=1;
        for(int i=2;i<=n;i++){
            char c=a[i-2];
            for(int j=1;j<=n;j++){
                if(c=='?')
                    dp[i][j]=s[i-1][i-1];
                else if(c=='I')
                    dp[i][j]=s[i-1][j-1];
                else dp[i][j]=(s[i-1][i-1]-s[i-1][j-1]+MOD)%MOD;
                s[i][j]=(s[i][j-1]+dp[i][j])%MOD;
            }
        }
        printf("%lld\n",s[n][n]);
    }
    return 0;
}

在这里插入图片描述

你可能感兴趣的:(基础DP)