uestc 250 windy数(数位dp)


题目链接

windy数

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

windy定义了一种windy数。

不含前导零且相邻两个数字之差至少为22的正整数被称为windy数。

windy想知道,在AABB之间,包括AABB,总共有多少个windy数?

Input

包含两个整数,AA BB

满足 1AB20000000001≤A≤B≤2000000000 .

Output

Sample input and output

Sample Input Sample Output
1 10
9

Source

Windy



题解:

数位dp,可以按平常老套路写,不过这一题比较特殊,可以预先处理出以i开头的长度为len的windy数(不管有无前导0),然后累加上去,详见代码。

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll d[11][15];
int a[15];
int abs(int x);
void init()
{
	for(int i=0;i<10;i++) d[1][i]=1;
	for(int i=2;i<=15;i++)
	{
		for(int j=0;j<10;j++)
		{
			for(int k=0;k<10;k++)
			{
				if(abs(j-k)>=2)
				d[i][j]+=d[i-1][k];
			}
		}
	}
}
ll cal(ll x)
{
	if(x==0) return 0;
	int len=0;
	while(x)
	{
		a[++len]=x%10;
		x/=10;
	}
	ll ans=0;
	for(int i=1;i=1;i--)
	{
		for(int j=0;j=2) ans+=d[i][j];
		if(abs(a[i+1]-a[i])<2)
		{
			flag=false;
			break;
		}
	}
	if(flag) ans++;
	return ans;
}


int main()
{
	init();
	ll a,b;
	while(~scanf("%lld%lld",&a,&b))
	{
		ll ans=cal(b)-cal(a-1);
		printf("%lld\n",ans);
	}
	return 0;
}

老套路写法:
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll d[15][12];
int a[15];
ll dfs(int pos,int pre,int st,int flag)  //st为0表示前面几位都是0,flag为0表示达到上限 
{
	ll ans=0;
	if(pos==0) return st==1;
	if(st&&flag)
	{
		if(~d[pos][pre]) return d[pos][pre];
	}
	int e=flag? 9:a[pos];
	for(int u=0;u<=e;u++)
	{
		if(abs(u-pre)>=2||!st)
		ans+=dfs(pos-1,u,st||u>0,flag||u


































你可能感兴趣的:(动态规划)