洛谷 P2657 [SCOI2009] windy 数(数位dp)
数位DP板子题
数位DP知识点:


AC代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int a,b,lim[15],dp[10][10];//第一维表示位数,第二维表示首数字是谁。dp表示这种请况下windy数有几个 int dfs(int pos,int pre,bool limit,bool lead){//当前位数,上个数字,是否限制大小,是否有前导零 if(pos==-1) return 1; if(!limit&&!lead&&dp[pos][pre]!=-1){//如果记录过,则直接返回 return dp[pos][pre]; } int temp=0; int up = limit?lim[pos]:9;//更改上界 for(int i=0;i<=up;i++){ if(abs(i-pre)<2&&!lead)//如果有前导0的话就不需要考虑相差大于2的情况 continue; temp+=dfs(pos-1,i,limit&&i==lim[pos],lead&&!i); } if(!limit&&!lead){//如果没有前导0且不是最高位,则保存下来便于下次查询 dp[pos][pre]=temp; } return temp; } int solve(int a){ int cnt=0; while(a>0){ lim[cnt++]=a%10;//记录每个数位 a/=10; } int ans=dfs(cnt-1,0,1,1);//因为从最高位进去。故limit=1,因为最高位取值是受到限制的。lead=1,因为最高位的更高位一定为0. return ans; } int main(){ memset(dp,-1,sizeof(dp));//在这里初始化,方便查询 scanf("%d%d",&a,&b); printf("%d\n",solve(b)-solve(a-1)); return 0; }

浙公网安备 33010602011771号