1. 程式人生 > >bzoj1026 windy數 數位dp 記憶化搜尋

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; }