Number String HDU - 4055 (递推dp+难)

传送门

题意:给出一行字符串,问用数字构成这个字符串的形式一共有多少种方案?

题解:最主要需要定义出状态:dp[i][j]表示符合第1-i的字符的情况下,最后一位是j的情况,所以递推方程为:

(1).当第i位字符是D时,此时dp[i][j]=\sum_{k=j}^{i-1}dp[i-1][k]

(2).当第i位字符是I时,此时dp[i][j]=\sum_{k=1}^{j-1}dp[i-1][k]

(3).当第i位字符是?时,此时dp[i][j]=\sum_{k=1}^{i-1}dp[i-1][k]

最后再使用一个s数组进行前缀和优化

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=1e3+50;
const int mod=1000000007;

int dp[maxn][maxn],s[maxn][maxn],N;
char str[maxn];

void solve()
{
    memset(dp,0,sizeof(dp));
    memset(s,0,sizeof(s));
    s[1][1]=dp[1][1]=1;
    N=strlen(str+2)+1;
    for(int i=2;i<=N;i++){
        for(int j=1;j<=i;j++){
            if(str[i]=='D'){
                dp[i][j]=(s[i-1][i-1]-s[i-1][j-1])%mod;
            }
            if(str[i]=='I'){
                dp[i][j]=s[i-1][j-1];
            }
            if(str[i]=='?'){
                dp[i][j]=s[i-1][i-1];
            }
            s[i][j]=(s[i][j-1]+dp[i][j])%mod;
        }
    }
    printf("%d\n",(s[N][N]+mod)%mod);
}

int main()
{
    while(~scanf("%s",str+2)){
        solve();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/86512670