bzoj1026: [SCOI2009]windy数---数位dp

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

数位dp,前导0的情况要考虑掉,dp【i】【j】【2】开三位表示i长度,j前一位是什么,k前面是不是全是前导0

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 100003
#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=100+10,maxn=1200000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int dp[N][N][2],digit[N];
int dfs(int len,int state,bool ok,bool fp)
{
    if(!len)return 1;
    if(!fp&&dp[len][state][ok]!=-1)return dp[len][state][ok];
    int ret=0,fpmax=fp ? digit[len] : 9;
    for(int i=0;i<=fpmax;i++)
    {
        if(ok&&abs(i-state)<2)continue;
        ret+=dfs(len-1,i,ok|i,fp&&i==fpmax);
    }
//    printf("%d %d %d\n",len,state,ret);
    if(!fp)dp[len][state][ok]=ret;
    return ret;
}
int solve(int x)
{
    int len=0;
    while(x)
    {
        digit[++len]=x%10;
        x/=10;
    }
    return dfs(len,0,0,1);
}
int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    memset(dp,-1,sizeof dp);
    printf("%d\n",solve(b)-solve(a-1));
    return 0;
}
/********************

********************/
View Code

 

posted @ 2018-04-13 00:25  walfy  阅读(...)  评论(... 编辑 收藏