数位DP【模板】

经典题型

数位 DP 问题往往都是这样的题型,给定一个闭区间 $[l, r]$,让你求这个区间中满足 某种条件 的数的总数。

强烈推荐 OI Wiki——数位DP

例题

BZOJ 1026

题目:windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

代码:

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

int A, B;
int f[11][12];
vector<int>dim;

int dfs(int x, int st, int op)
{
    //printf("%d %d %d
", x, st, op);
    if(!x)  return 1;
    if(!op && ~f[x][st])  return f[x][st];
    int maxx = op ? dim[x] : 9;     //如果前面全是相等,则这一位不能超过dim[x];否则无限制
    int ret = 0;
    for(int i = 0;i <= maxx;i++)    //枚举当前位
    {
        if(abs(st - i) < 2) continue;
        if(st == 11 && i == 0)      //把前导0也作为一种数字,可以是其他数,但与1~9至少相差2
            ret += dfs(x-1, 11, op & (i == maxx));
        else
            ret += dfs(x-1, i, op & (i == maxx));
    }
    if(!op)  f[x][st] = ret;
    return ret;
}

int solve(int x)
{
    memset(f, - 1, sizeof(f));
    dim.clear();
    dim.push_back(-1);  //填充一位,值随意
    //int t = x;
    while(x)
    {
        dim.push_back(x % 10);
         x /= 10;
    }
    return  dfs(dim.size()-1, 11, 1);
}

int main()
{
    scanf("%d%d", &A, &B);
    printf("%d
", solve(B)- solve(A-1));
    return 0;
}
原文地址:https://www.cnblogs.com/lfri/p/11347372.html