动态规划——数位dp入门(一)

动态规划——数位dp(入门)

数位dp一般用来解决:求在某一数据范围内的满足某项特征的数的个数这类问题。在dp数组中,一般第一项i用于表明
数字的位数,第二项j用于储存状态(有时会用多项)。



hdu2089 不要62

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

题意就是让你求出在两个数之间的不含有‘’数字4‘’和‘’62‘’的数。


#include
#include
#include
#include
#include
using namespace std;

int num[10];  //用于储存数,方便对数进行按位操作
int dp[10][2];//0=吉利数,1=最高位为2的吉利数
int bei10[8];

int shudp(int x)
{
    int xx = x;
    int ding = 0;
    int bujili = 0;//不吉利数的个数
    bool flag = false;

    while(x > 0)  // 把这个数按位分开
    {
        num[++ding] = x%10;
        x = x/10;
    }
    num[ding+1] = 0;

    for(int i = ding; i >= 1; i--)
    {
        bujili += num[i]*(bei10[i-1]-dp[i-1][0]);
        if(flag)
        {
            bujili += dp[i-1][0]*num[i];
        }
        else
        {
            if(num[i] > 4)
                bujili += dp[i-1][0];
            if(num[i+1] == 6 && num[i] > 2)
                bujili += dp[i][1];
            if(num[i] > 6)
                bujili += dp[i-1][1];
            if(num[i] == 4 || (num[i+1] == 6 && num[i] == 2) )
                flag = true;
        }
    }
    if(flag)  // 如果这个数本身也是不吉利数,要单独处理。
        bujili++;

    return
        xx-bujili;
}

void init()
{
    memset(dp,0,sizeof(dp));
    dp[0][0] = 1;
    bei10[0] = 1;
    for(int i = 1; i <= 9; i++)
    {
        dp[i][0] = dp[i-1][0]*9-dp[i-1][1];
        dp[i][1] = dp[i-1][0];
        bei10[i] = bei10[i-1]*10;
    }

}

int main()
{
    int left,right;
    init();
    while(~scanf("%d%d",&left,&right))
    {
        if(left == 0 && right == 0)
            return 0;
        printf("%d\n",shudp(right)-shudp(left-1));// 对于某一区间内的求取,可以通过做差来获得。
    }
    return 0;
}


思路:预处理好不同位数长度的吉利数和最高位为二的吉利数,从最高位向下遍历,找出所有的非吉利数(找反面好想些),每次找的时候都是对长度-1进行的处理,因此只需再考虑62的特殊情况即可。

你可能感兴趣的:(算法,动态规划)