[SCOI2009] windy数

[SCOI2009] windy数

题目大意:求\([L,R]\)中相邻每一位之差至少大于\(2\)的数字个数,(只有一位也算)

Solution

数位\(dp\)直接搞,对于前导零,其实不用卡下界,只要一个用一个状态来表示就好,还可以取\(0\)

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#define pf(x) printf("%d\n", x);

int dp[15][15];
int a[15];

int dfs(int pos, int last, bool uflag, bool dflag){
	if(pos < 0 && last >= 0) return 1;
	else if(pos <0) return 0;//全是0 
	if(!uflag && !dflag && dp[pos][last] != -1) return dp[pos][last];//不用卡上下界,是一个完全状态 
	int up = uflag ? a[pos] : 9;//取上界 
	int tmp = 0;//不用取下界,因为可以为0 
	for(int i = 0; i <= up; ++i){
		if(abs(i - last) >= 2 || last == -233){
			if(i == 0 && dflag)//依然为0 
				tmp += dfs(pos - 1, -233, uflag && (i == up), (i == 0) && dflag );
			else //随便了 
				tmp += dfs(pos - 1, i, uflag && (i == up), 0);
		}
	}
	if(!uflag && !dflag) dp[pos][last] = tmp;//完全状态 
	return tmp;
}

inline int cal(int x){
	int cnt = -1; 
	memset(a, 0, sizeof(a));
	while(x){
		a[++cnt] = x % 10;
		x /= 10;
	}
	int qwq = dfs(cnt, -233, 1, 1);
	return qwq;
}

int main(){
	int l, r;
	scanf("%d %d", &l, &r);
	memset(dp, -1, sizeof(dp));//0
	printf("%d", cal(r) - cal(l - 1));
	return 0;
}

posted @ 2018-09-10 17:38  LMSH7  阅读(115)  评论(0编辑  收藏  举报