bzoj1026 windy数 数位dp 记忆化搜索

bzoj1026 windy数
题目大意:求[A,B]相邻两位差>=2的个数 1 <= A <= B <= 2000000000
题解:
在网上找了找题解都是用上一种方法(预处理+递推)写的
然而自认为记忆化搜索才是数位dp的通解(勿喷= =
记忆化搜索记录三个变量

int dfs(int pos,int pre,bool limit)

分别记录 当前位置 前一位数 是否有限制
如果(!limit) 当统计完这次dfs(pos,pre,limit)
将这次返回值记录在dp[pos,pre]里
下次没有(!limit)需要调用dfs(pos,pre,limit)时 直接调用dp[pos,pre]即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std; 
int dp[50][20],bit[50];
int a,b;
//当前位置 前一位 是否有限制
int dfs(int pos,int pre,bool limit){
    int p;
    if(pos<=0) return 1;
    if(pre>=0 && !limit && dp[pos][pre]!=-1) return dp[pos][pre]; 
    int end=(limit?bit[pos]:9);
    int ret=0;
    for(int i=0;i<=end;i++)
        if((int)abs((double)i-pre)>=2){
            p=i;
            if(pre==-10 && i==0) p=pre;
            ret+=dfs(pos-1,p,limit&&(end==i));
        }
    if(pre>=0 && !limit) dp[pos][pre]=ret;
    return ret;
}
int solve(int x){
    int len=0;
    while(x) bit[++len]=x%10,x/=10;
    memset(dp,255,sizeof(dp));
    return dfs(len,-10,1);
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%d%d",&a,&b);
    printf("%d\n",solve(b)-solve(a-1));
    //printf("%d\n",solve(b));
    return 0;
}

你可能感兴趣的:(dp,记忆化搜索,bzoj,数位dp)