數位DP入門-SCOI2009

上題目windy數

題目描述

Description
windy定義了一種windy數。不含前導零且相鄰兩個數字之差至少爲2的正整數被稱爲windy數。 windy想知道,在A和B之間,包括A和B,總共有多少個windy數?
Input
包含兩個整數,A B。
Output
一個整數
Sample Input
【輸入樣例一】
1 10
【輸入樣例二】
25 50
Sample Output
【輸出樣例一】
9
【輸出樣例二】
20
HINT
【數據規模和約定】
100%的數據,滿足 1 <= A <= B <= 2000000000 。

解析

這是一道很簡單的數位DP題目,基本上直接看代碼加註釋就能懂。

//dp[i][j]表示長度爲i,最高位是j且符合要求的個數
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int dp[10][11],bit[11],len;
long long a,b,ans=0;
void init()//初始化
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=9;i++)dp[1][i]=1;
    for(int i=2;i<=10;i++)
        for(int j=0;j<=9;j++)
            for(int k=0;k<=9;k++)
                if(abs(j-k)>=2)dp[i][j]+=dp[i-1][k];//j與k絕對值大於2
}
int solve(int n)
{
    len=0,ans=0;//len表示n的長度,ans表示0-n中的個數
    while(n)
    {
        bit[++len]=n%10;
        n/=10;
    }
    for(int i=1;i<len;i++)
        for(int j=1;j<=9;j++)
            ans+=dp[i][j];//長度不超過len
    for(int i=1;i<bit[len];i++)ans+=dp[len][i];//長度等於len但最高位小於n
    for(int i=len-1;i>=1;i--)//長度等於len且最高位等於n
    {
        for(int j=0;j<bit[i];j++)
            if(abs(j-bit[i+1])>=2)ans+=dp[i][j];
        if(abs(bit[i+1]-bit[i])<2)break;
    }
    return ans;
}
int main()
{
    scanf("%d%d",&a,&b);
    init();
    printf("%d\n",solve(b+1)-solve(a));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章