码迷,mamicode.com
首页 > 其他好文 > 详细

数位dp

时间:2016-04-11 20:49:42      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

1、 hdoj 2089 不要62

题意: 不吉利数为数中含有4或者62,  单个6或者单个2或者26都是不是不吉利数; 求给定区间里的吉利数;

//代码1 ; 
#include <cstdio>
#define MAXN 10
#include <cstring>
using namespace std;
int dp[MAXN][3];

// dp[i][0] 长度为i, 不含有不吉利数字
// dp[i][1] 长度为i, 当前位为6 
// dp[i][2] 长度为i, 含有不吉利数字 
void init()
{
    dp[0][0]=1;   
    dp[0][1]=dp[0][2]=0;
    for(int i=1; i<= 10; i++)
    {
        dp[i][0]= dp[i-1][0]*9 - dp[i-1][1];  //在不含不吉利数的数的末位添加除去 4 的其他九个数, 减去后边添2的情况 ; 
        dp[i][1]= dp[i-1][0];                 //在不含不吉利数的末位添加6 ; 
        dp[i][2]= dp[i-1][2]*10 + dp[i-1][0] + dp[i-1][1];  //不吉利数*10 + 吉利数末尾加4 + 末尾为6的吉利数后边添2; 
    }    
}

int bit[MAXN];
int solve(int n)
{
    int len=0;
    memset(bit, 0, sizeof(bit));
    int tmp=n;
    while(n)
    {
        bit[++len]= n%10;
        n /= 10; 
    } 
    int ans=0;
    int flag=0;
    for(int i=len; i>=1; i--)
    {
        ans= ans + bit[i]*dp[i-1][2];     //由上位所有不吉利数推导; (不含前导零, 所以乘以bit[i];);  
        if(flag) ans+= bit[i]*dp[i-1][0]; //之前出现的不吉利数字 ; 
        else
        {
            if(bit[i] >4) ans +=dp[i-1][0];  //出现4 ; 
            if(bit[i] >6) ans +=dp[i-1][1];  //出现6 ;  
            if(bit[i+1]== 6 && bit[i] >2) ans +=dp[i][1];  //出现62 ; 
        }
        if(bit[i+1] ==6&& bit[i]==2) flag =1;
        if(bit[i]== 4) flag=1;
    }
    if(flag) ans++;
    return tmp-ans;  //所有的数减去不吉利数 ; 
}
int main()
{
    int n, m;
    init();
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if(!n && !m) break;
        int ans=solve(m)- solve(n-1);
        printf("%d\n", ans);
    }
    return 0;
}

 

//记忆化搜索(不好理解!! );
#include <cstdio>
#include <cstring>
const int N = 10;
using namespace std ;

int bit[N];
int dp[N][2];// dp[i][is6] is the number of i-len digits with (if prevent number is 6), its digits are from 0-9  
int dfs(int len, bool is6, bool ismax)
{
    if(len==0) return 1;
    if(!ismax && dp[len][is6] >= 0) return dp[len][is6];
    
    int cnt=0;
    int Max= ismax? bit[len]: 9;
    for(int i=0; i<= Max; i++)     //枚举数位 ; 
    {
        if(i==4 || is6 && i == 2)  // unluck digit 
            continue;
        cnt += dfs(len-1, i==6, ismax && i==Max);
    }
    return ismax? cnt: dp[len][is6]= cnt;
}

int solve(int num)
{
    int len=0;
    while(num)
    {
        bit[++len]=num%10;
        num /= 10;
    }
    return dfs(len, false, true);
}

int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if(!n && !m) break;
        memset(dp, -1, sizeof(dp));
        printf("%d\n", solve(m)-solve(n-1));
    }
    return 0;
}

 

2、

数位dp

标签:

原文地址:http://www.cnblogs.com/fengshun/p/5379923.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!