【[SCOI2009]windy数】数位DP
数位DP,那么我们考虑记忆化搜索解决。
状态:DP[X][Y] X表示考虑到第几位,Y考虑到这个数的前一个数什么,状态保存从此状态出发达到完成结果的方案数(大概意思理解到就好)。
实现:搜一遍
坑难点:有个无前导0的限制以及不能超过那个数最高位的限制,因此我们在搜索中增加两个bool分别,shangxian记录表示目前是不是仍然在达到原数边界位数上讨论(eg:43278 我们的len==3 last==3,且前面讨论的4,此时我们讨论的位上的数数不能超过2) qdling表示现在是不是还在前导0(前面的位是不是全是0)
数位dp也是刚学qwq,考虑多有不周,需要多加学习。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; int dp[15][15],num[15];//len last int a,b; int dfs(int len,int last,bool shangxian,bool qdling) { if(len==0) return 1; if(!qdling&&!shangxian&&dp[len][last]!=-1) return dp[len][last]; int p,cnt=0,maxx=(shangxian?num[len]:9); for(int i=0;i<=maxx;i++) { if(abs(i-last)<2)continue; p=i; if(qdling&&i==0) p=-233; cnt+=dfs(len-1,p,(shangxian)&&(i==maxx),(p==-233)); } if(!shangxian&&!qdling) dp[len][last]=cnt; return cnt; } int solve(int x) { int k=0; while(x) { num[++k]=x%10; x/=10; } memset(dp,-1,sizeof(dp)); return dfs(k,-233,true,true); } int main() { scanf("%d%d",&a,&b); printf("%d\n",solve(b)-solve(a-1)); }