HDU 2089 数位DP + 特殊数字的限制

89 篇文章 1 订阅

数位DP + 特殊数字的限制

题意:

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

思路:

​ 最开始可以想到直接一个一个数字去试试,找一找是否满足情况,这是笨办法,也会超时。

而数位DP可以用数字的特性去解决:

  • 一个数字有位数的特性
  • 一个数字可以拆分为不同的数字的和例如:314可以拆分为:0~99,100~199,200~299,300~309,310~314

利用上边的特性定义: dp[i][j] 为数字的第i位以j数字开头的满足题意的个数

那么便有: dp[i][j]=9j=0dp[i1][j] ,而62 和 4 只需直接加上限制条件就行。

  • 其中一个点需要注意的是,当高位算了之后算低位上的数字,其实是在高位的基础上算的,所以高位是4或者62的时候需要跳出,已经不存在满足的数字了。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n,m;
int dp[10][10];

void DP()
{
    dp[0][0] = 1;
    for(int i = 1;i <= 7; i++) {
        for(int j = 0;j <= 9; j++) {
            for(int k = 0;k <= 9; k++) {
                if(j != 4 && !(j == 6 && k == 2))
                    dp[i][j] += dp[i-1][k];
            }
        }
    }
}

int solve(int a)
{
    int temp[10];
    int pos = 0;
    while(a) {
        temp[++pos] = a%10;
        a /= 10;
    }
    temp[pos+1] = 0;
    int ans = 0;
    for(int i = pos;i >= 1; i--) {
        for(int j = 0;j < temp[i]; j++) {
            if(j != 2 || temp[i+1] != 6)
                ans += dp[i][j];
        }
        if(temp[i] == 4 || (temp[i+1] == 6 && temp[i] == 2)) break;
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    //freopen("in.txt","r",stdin);
    DP();
    while(scanf("%d%d",&n,&m) != EOF) {
        if(n == 0 && m == 0) break;
        printf("%d\n",solve(m+1)- solve(n));
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值