bzoj1026 windy數 數位dp 記憶化搜尋
阿新 • • 發佈:2018-12-23
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;
}