1. 程式人生 > >Luogu-2657 [SCOI2009]windy數

Luogu-2657 [SCOI2009]windy數

很少做數位\(dp\)的題,做道題學習一下吧。

記憶化搜尋,\(f[10][10][2][2]\)分別記錄當前位置,上一位數,是否有前導零和是否有大小上限。

題目要滿足相鄰兩個數相差不小於2,如果有前導零就可以無視這個限制,如果沒有就要先判斷一下。

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[10][10][2][2],c[10],num,a,b;
int dfs(int wei,int last,int qdl,int xz){
    if(wei==0) return 1;
    if(f[wei][last][qdl][xz])
        return f[wei][last][qdl][xz];
    int lim=xz?c[wei]:9,&tot=f[wei][last][qdl][xz];
    for(int i=0;i<=lim;i++){
        if(!qdl&&abs(last-i)<2)
            continue;
        tot+=dfs(wei-1,i,qdl&&!i,xz&&i==lim);
    }
    return tot;
}
inline int work(int x){
    num=0;
    memset(f,0,sizeof(f));
    while(x){
        c[++num]=x%10;
        x/=10;
    }
    return dfs(num,0,1,1);
}
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%d%d",&a,&b);
    printf("%d\n",work(b)-work(a-1));
    return 0;
}