1. 程式人生 > >2018.09.29【BZOJ1026】【洛谷P2657】【SCOI2009】windy數(數位DP)

2018.09.29【BZOJ1026】【洛谷P2657】【SCOI2009】windy數(數位DP)

洛谷傳送門

解析:

由於資料範圍很小(相對於大部分數位DPDP題來說)。
我們只記錄當前位,當前位數字,是否是前導0,是否達到上界。
簡單DP記憶化搜尋一下就好了。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
int getint(){
	re int num;
	re int c;
	while(!isdigit(c=
gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } int len,mark[12]; int f[12][10][2][2]; inline int dp(int pos,int num,bool pre0,bool limit){ if(pos>len)return 1; if(~f[pos][num][pre0][limit])return f[pos][num][pre0][limit]; int res=0; int r; if(limit)
r=mark[pos]; else r=9; for(int re i=0;i<=r;++i){ if(pre0||abs(i-num)>=2) res+=dp(pos+1,i,pre0&&i==0,limit&&i==r); } return f[pos][num][pre0][limit]=res; } inline int solve(int a){ memset(f,-1,sizeof f); len=0; do{ mark[++len]=a-a/10*10; a/=10; }while(a); reverse(mark+1,mark+
len+1); return dp(1,0,1,1); } signed main(){ int l=getint(),r=getint(); cout<<(solve(r)-solve(l-1)); return 0; }