P2064【SCOI2009 day1】windy数(数位dp)

来源:互联网 发布:弗洛伊德算法 例子 编辑:程序博客网 时间:2024/06/04 01:08

问题描述

windy定义了一种windy数。
不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。比如31, 135, 13579都是windy数。单独一个数字也算windy数比如1,2,3,…,9都是。
windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

输入格式

两个整数,A B。

输出格式

一个整数

样例输入

【输入样例一】
1 10

【输入样例二】
25 50

样例输出

【输出样例一】
9

【输出样例二】
20

题解

dp【i】【j】表示到i位时且最高位为j时的种类数
分三种情况讨论:
ans=0;
1.长度<=n-1 时的种类数
2.长度==n 并且首位数字小于等于最高位的种类数
3.长度==n 并且当首位数字等于最高位的种类数

代码

#include<stdio.h>#include<algorithm>#include<cmath>#include<cstring>#include<queue>#include<cstdio>#include<iostream>using namespace std;int dp[20][11];int a,b;int n;int d(char s[]){    int i,j,k;    int ans=0;    n=s[0]-'0';    for(i=1;i<=n-1;i++)      for(j=1;j<=9;j++)        ans+=dp[i][j];    for(i=1;i<s[n]-'0';i++) ans+=dp[n][i];    for(i=n-1;i>=1;i--){        int tx=s[i+1]-'0';        for(j=0;j<s[i]-'0';j++)        {            if(abs(tx-j)>=2) ans+=dp[i][j];        }        if(abs(s[i+1]-s[i])<2) break;    }    return ans;}int main(){    int i,j,k;    int a1,b1;     int cnt=0;    cin>>a1>>b1;   char s1[20],s2[20];   while(a1) s1[++cnt]=a1%10+'0',a1/=10;   s1[0]=cnt+'0';   cnt=0;   b1++;   while(b1) s2[++cnt]=b1%10+'0',b1/=10;   s2[0]=cnt+'0';    for(i=0;i<=9;i++) dp[1][i]=1;    for(i=2;i<=11;i++){        for(j=0;j<=9;j++)        {            for(k=0;k<=9;k++)            {                if(abs(j-k)>=2){                    dp[i][j]+=dp[i-1][k];                }            }         }    }    cout<<d(s2)-d(s1);}
原创粉丝点击