[hdu 2089]简单数位dp

一个不错的讲解数位dp的博客:http://blog.csdn.net/wust_zzwh/article/details/52100392

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

这个题数据范围比较小,所以暴力也可以过,像这样:

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

const int maxn=1000005;
int a[maxn];

bool laoer(int x)
{
    int b[10]={};
    int cnt=0;
    do{
        b[cnt]=x%10;
        x/=10;
        cnt++;
    }while (x);
    for (int i=0;i<cnt;i++)
    {
        if (b[i]==4||b[i]==2&&b[i+1]==6) return true;
    }
    return false;
}

int main()
{
    for (int i=1;i<=1000000;i++)
    {
        if (laoer(i)) a[i]=1;
        a[i]+=a[i-1];
    }
    int n,m;
    while (~scanf("%d%d",&n,&m) && (n||m))
    {
        printf("%d\n",(m-n+1)-(a[m]-a[n-1]));
    }
    return 0;
}

但是还是数位dp的方法更厉害一点。实质上就是对于一个给定的范围,用记忆化搜索搞出来。

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

int b[20];
int dp[20][2];

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 (i==4||limit&&i==2) continue;
        if (i<b[pos]||preok) ans+=dfs(pos-1,1,i==6);
        else ans+=dfs(pos-1,0,i==6);
    }
    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,0);
}

int main()
{
    memset(dp,-1,sizeof(dp));
    int n,m;
    while (~scanf("%d%d",&n,&m) && (n||m))
    {
        printf("%d\n",solve(m)-solve(n-1));
    }
    return 0;
}

 

posted @ 2017-07-18 20:03  ACMsong  阅读(150)  评论(0编辑  收藏  举报