[hdu 4734]数位dp例题

通过这个题目更加深入了解到了数位dp在记忆化搜索的过程中就是实现了没有限制条件的n位数的状态复用。

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

int f2[20];
int b[20];
int dp[20][4700];
int A;

int F(int x)
{
    int a[20];
    int cnt=0;
    int ret=0;
    do{
        a[cnt]=x%10;
        x/=10;
        cnt++;
    }while (x);
    for (int i=cnt-1;i>=0;i--)
    {
        ret=ret*2+a[i];
    }
    return ret;
}

int dfs(int pos,int preok,int limit)
{
    if (pos==-1) return 1;
    if (preok && dp[pos][limit]!=-1) return dp[pos][limit];
    int up=preok?9:b[pos];
    int ans=0;
    for (int i=0;i<=up;i++)
    {
        if (limit-f2[pos]*i<0) continue;
        if (i<b[pos]||preok) ans+=dfs(pos-1,1,limit-f2[pos]*i);
        else ans+=dfs(pos-1,0,limit-f2[pos]*i);
    }
    if (preok) dp[pos][limit]=ans;
    return ans;
}

int solve(int n)
{
    if (n<0) return 0;
    int cnt=0;
    int now=n;
    do{
        b[cnt]=now%10;
        now/=10;
        cnt++;
    }while (now);
    return dfs(cnt-1,0,F(A));
}

int main()
{
    memset(dp,-1,sizeof(dp));
    f2[0]=1;
    for (int i=1;i<=20;i++) f2[i]=f2[i-1]*2;
    int t;
    scanf("%d",&t);
    for (int cas=1;cas<=t;cas++)
    {
        int n;
        scanf("%d%d",&A,&n);
        printf("Case #%d: %d
",cas,solve(n));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/acmsong/p/7202730.html