[BZOJ] ]1026: [SCOI2009]windy数

需要记录的信息有:做到了第几位,上一位的数字,是否随便填

记搜实现起来实在是方便,数位DP应该不会卡常数

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}
#define space() putchar(' ')
#define nextline() putchar('\n')
void pot(int x){if(!x)return;pot(x/10);putchar('0'+x%10);}
void out(int x){if(!x)putchar('0');if(x<0)putchar('-'),x=-x;pot(x);}

const int MAXN = 22;

int f[MAXN][MAXN];

int a[MAXN],top;
int dfs(int dp,int lst,bool lim){
	if(dp==0)return 1;
	if(!lim&&lst>=0&&f[dp][lst]!=-1)return f[dp][lst];
	int ret=0,up=(lim?a[dp]:9),pos;
	for(int i=0;i<=up;i++){
		if(abs(i-lst)<2) continue;	
		pos=i;
		if(i==0&&lst==-3) pos=-3;
		ret+=dfs(dp-1,pos,lim&(i==up));
	}
	if(!lim&&lst>=0) f[dp][lst]=ret;
	return ret;
}

int solve(int x){
	top=0;
	while(x){
		a[++top]=x%10;
		x/=10;
	}
	memset(f,-1,sizeof(f));
	return dfs(top,-3,1);
}

int main(){
	int L,R;
	L=rd();R=rd();
	out(solve(R)-solve(L-1));
	return 0;
}
posted @ 2018-10-19 11:16  GhostCai  阅读(58)  评论(0编辑  收藏