Windy 数

题目链接:https://loj.ac/problem/10165#submit_code

思路:数位dp,记录是否为前导0,已经是否为上边界和前一个数的值即可,如果前面已经有数了,那要和前一个数之差的绝对值要大于等于2才行。具体实现请看代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[30];
ll dp[30][20];
//pos : 位数  qd : 是否为前导  flag : 是否处于上边界   x : 上一个位数的值
ll dfs(int pos,bool qd,bool flag,int x)
{
    if(pos==0)
        return 1;
    int up=flag?a[pos]:9;//确定上边界
    if((!flag)&&(!qd)&&dp[pos][x]!=-1)//如果之前已经求出,则直接返回
        return dp[pos][x];
    ll tmp=0;
    for(int i=0;i<=up;i++)
    {
        if(i==0&&qd)//依旧是前导0
            tmp+=dfs(pos-1,qd,flag&&i==a[pos],0);
        else if(qd)//前面的数是前导0,这是第一个数,不需要考虑差要大于等于2
            tmp+=dfs(pos-1,false,flag&&i==a[pos],i);
        else if(abs(i-x)>=2)//要保证两个数的差大于等于2
            tmp+=dfs(pos-1,false,flag&&i==a[pos],i);
    }
    if((!flag)&&(!qd))
        dp[pos][x]=tmp;//记录值,方便下次直接返回
    return tmp;
}
ll fun(int x)
{
    int pos=0;
    while(x)//将x的每一位进行分解
    {
        a[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,true,true,0);
}
int main()
{
    memset(dp,-1,sizeof(dp));
    int l,r;
    cin>>l>>r;
    cout<<fun(r)-fun(l-1)<<endl;
}
原文地址:https://www.cnblogs.com/zcb123456789/p/13749082.html