HYSBZ1206->数位DP
题意:
求一个区间中有多少个数其相邻两位之间的差值大于等于2,不含前导0,只有一位的数字也都算作符合规则。
题解:
典型的数位DP的题目。
dp[i][j]代表第i位为j时,符合要求的数字有多少个。
先初始化,从第1位到第11位依次统计,状态转移方程为:
dp[i][j] += dp[i-1][k] (k - j >= 2 || j - k >= 2)在解决问题的过程中,需要从最高位向最低位统计有多少个数能被统计
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
int dp[12][10] , n[12];
void init()
{
memset(dp , 0 , sizeof(dp)) ;
for(int i = 0 ; i <=9 ; i ++) dp[1][i] = 1 ;
for(int i = 2 ; i <= 11 ; i ++)
{
for(int j = 0 ; j <= 9 ; j ++)
{
for(int k = 0 ; k <= 9 ; k ++)
if(k - j >= 2 || j - k >= 2) dp[i][j] += dp[i-1][k] ;
}
}
}
int solve(int num)
{
int cnt = 0 , ans = 0;
while(num)
{
n[++cnt] = num % 10 ;
num /= 10 ;
}
n[cnt + 1] = 0 ;
for(int i = 1 ; i < cnt ; i ++)
for(int j = 1 ; j <= 9 ; j ++)
ans += dp[i][j] ;
for(int i = 1 ; i < n[cnt] ; i ++ ) ans += dp[cnt][i] ;
for(int i = cnt - 1 ; i >= 1 ; i --)
{
for(int j = 0 ; j <= n[i] - 1 ; j ++)
{
//判断上一位和当前的数的差值
if(fabs(n[i+1] - j) >= 2) ans += dp[i][j] ;
}
if(fabs(n[i] - n[i+1]) < 2) break ;
}
return ans ;
}
int main()
{
int l , r ;
init() ;
while(scanf("%d%d" , &l , &r) != EOF)
{
printf("%d\n" , solve(r + 1) - solve(l)) ;
}
return 0;
}