[BZOJ] ]1026: [SCOI2009]windy数

需要记录的信息有:做到了第几位,上一位的数字,是否随便填

记搜实现起来实在是方便,数位DP应该不会卡常数

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}
#define space() putchar(' ')
#define nextline() putchar('\n')
void pot(int x){if(!x)return;pot(x/10);putchar('0'+x%10);}
void out(int x){if(!x)putchar('0');if(x<0)putchar('-'),x=-x;pot(x);}

const int MAXN = 22;

int f[MAXN][MAXN];

int a[MAXN],top;
int dfs(int dp,int lst,bool lim){
    if(dp==0)return 1;
    if(!lim&&lst>=0&&f[dp][lst]!=-1)return f[dp][lst];
    int ret=0,up=(lim?a[dp]:9),pos;
    for(int i=0;i<=up;i++){
        if(abs(i-lst)<2) continue;  
        pos=i;
        if(i==0&&lst==-3) pos=-3;
        ret+=dfs(dp-1,pos,lim&(i==up));
    }
    if(!lim&&lst>=0) f[dp][lst]=ret;
    return ret;
}

int solve(int x){
    top=0;
    while(x){
        a[++top]=x%10;
        x/=10;
    }
    memset(f,-1,sizeof(f));
    return dfs(top,-3,1);
}

int main(){
    int L,R;
    L=rd();R=rd();
    out(solve(R)-solve(L-1));
    return 0;
}
posted @ 2018-10-19 11:16  GhostCai  阅读(...)  评论(... 编辑 收藏