不要62(HDU 2089) 数位dp入门

链接

Click here to see the original question

题目描述

杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。

输入

输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。

输出

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。

代码

#include <bits/stdc++.h>
using namespace std;
int n, m, bit[11], dp[11][2];

int DFS(int pos, bool isSix, bool isMax) {
    //pos表示当前遍历的位数,isSix表示上一位是否为6,isMax表示上一位的值是否为相应的最大可能值
    if(pos == 0) return 1;
    //已经把所有的位数都遍历完毕,确定了一种可行方案

    if(!isMax && dp[pos][isSix]) return dp[pos][isSix];
    //若当前pos的值不是当前位的最大可能值
    //那么相应的答案是可以重复利用的,dp[pos][isSix] != 0 就保证了这个数在之前已经计算过了,直接返回就好
    //比如说,对于区间0 - 567, 100、200、300的种类数其实是一样的
    //答案又分为上一位是6和不是6两种情况,要分开存储起来

    int cnt = 0;//用来存储种类数
    int maxNum = isMax ? bit[pos] : 9;
    //区间0 - 567 , pos = 3 时, 如果当前已经遍历到5了,那么枚举下一位的时候最大值只能到6
    for(int i = 0; i <= maxNum; i++){
        if(i == 4 || (isSix && i == 2)) continue;//过滤掉不合法的情况
        cnt += DFS(pos - 1, i == 6, isMax && i == maxNum);
    }
    return isMax ? cnt : dp[pos][isSix] = cnt;
    //isMax为true时,没有存储的必要,比如对区间0 - 567,我们没必要把500-567区间的数据存储起来
}

int tran(int num) {
    int pos = 0;
    while(num){
        bit[++pos] = num % 10;
        num /= 10;
    }
    return DFS(pos, false, true);
}

int main() {
    while(cin >> n >> m){
        if(n == 0 && m == 0) break;
        cout<<tran(m) - tran(n - 1)<<endl;
    }
    return 0;
}

如果您觉得我的文章对您有帮助的话,可以点个赞,点个关注,也可以扫描下方二维码关注我。我将在这个公众号上更新自己的学习笔记,以及分享一些算法知识

Study and progress together with me!

img

猜你喜欢

转载自blog.csdn.net/qq_45359344/article/details/107625403
今日推荐