D - windy数 (数位DP)

人走茶凉 提交于 2019-12-24 00:03:03

D - windy数

 windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

题解:用dp[i][j]表示对前i位,在第i+1位为j时的windy数

代码解释:

/***********************************************/
int a[20];
ll dp[20][11];//记录前i位中windy数个数 
//因为前一位j为多少对后面的枚举是有影响的 

ll dfs(int cur,int pre,bool limit,bool lead) 
{	//lead用于判断从高位到低位枚举时有没有前导0,
	//如对1232
	//当前面几位枚举的都是0时,后面一位的枚举是不受前面一位限制的,
	//因为如果前面几位都是0,就相当于前几位是不存在的,
	//所以才有: if( abs(i-pre) >=2 || lead) 
	//这就是枚举条件 
	if(cur==0) return 1;
	if(!limit && dp[cur][pre]!=-1 && pre>0) return dp[cur][pre];
	// pre>0 ,如果pre==0,涉及到位数,需要再次循环 
	ll ans=0;
	int cu=limit?a[cur]:9;
	
	for(int i=0;i<=cu;i++)
	{
		if( abs(i-pre) >=2 || lead){
			//cout<<cur<<" "<<i<<"  "<<endl;;
			ans+=(dfs(cur-1,i,limit & (i==a[cur]) , lead&(i==0) ));
		}
	}
	if(!limit) dp[cur][pre]=ans;//还是那个记忆化 
	return ans;
}

ll solve(ll x)
{
	int cut=0;
	while(x){
		a[++cut]=(x%10);
		x/=10;
	}
	return dfs(cut,-2,1,1);
}

int main()
{
	ll a,b;
	while(cin>>a>>b)
	{
		mem1(dp);
		
		cout<<solve(b)-solve(a-1)<<endl;
		//cout<<solve(10);
	}

	return 0;
}

  

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!