zoukankan      html  css  js  c++  java
  • [SCOI2009]windy数

    这是本蒟蒻做的第一道数位DP。。。(大佬勿喷QVQ

    这个题据说比较裸?WTF我咋不知道 QVQ

    emm。。。根据题意我们可以发现,通过枚举每个的位置的数我们可以递推出满足条件的数的数量

    这里用 f[i][j] 表示 有 i 位 最高位的数是 j 有f[i][j]个方案

    那么我们就可以 轻松 得到DP柿子啦~~~

    注意:当我们得到A B这两个数的时候,我们要对 B 和 A-1 操作。。。

      为什么A要-1呢?

      因为我们得到的windy数是从 0~B 的那么我们重复的就是 0~A-1 的windy数

    接下来要处理第二步?就是判断哪些答案合法

    合法答案分为三部分:

    假使我们的这个数为 X 有 K 位 一个数组 S 记录每位数是什么

    first:位数小于 K 必然的这些数都小于X 所以我们把 f 数组无脑加上就好

    second:位数等于 K 那么我们首先可以确定,最高位小于 S[K] 的答案肯定合法

    third:下面就是最难搞的地方,我们要一位一位的判断答案的合法性

      举个例子 19260817 135 我们倒着枚举每一位 for(int i=K-1;i>=1;i++);

      我们可以发现对于第 i 位的数,我们可以通过枚举这个数 j,此时要满足两个条件。

      小于 S[i] 而且 abs ( j - S[i] ) >= 2 那么选择这个数一定是合法的。

      依次类推。。。但是,如果当 S[i+1] - S[i] < 2 时 那么以后的数一定是不合法的。。。

      因为这两个数已经不满足条件了。。。

    那么,我们的问题就解决了?

      NO NO NO

    当我们发现每一位都合法,就是这个数本身就是一个windy数那么我们的答案就应该+1

    呆码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #define ll long long
    using namespace std;
    
    ll A,B,f[15][15]; // 多少位数 最高位是多少 有多少方案 
    int s[21];
    
    inline void DP()
    {
        for(int i=0;i<=9;i++)
            f[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)
                        f[i][j]+=f[i-1][k];
    }
    
    inline ll solve(int x)
    {
        memset(s,0,sizeof(s));
        if(x==0) return 0;
        int num=0; ll ans=0;
        while(x)
        {
            s[++num]=x%10;
            x/=10;
        }
        for(int i=1;i<=num-1;i++)
            for(int j=1;j<=9;j++)
                ans+=f[i][j];
        for(int i=1;i<=s[num]-1;i++)
            ans+=f[num][i];
        
        for(int i=num-1;i>=1;i--)
        {
            for(int j=0;j<=s[i]-1;j++)
                if(abs(j-s[i+1])>=2)
                    ans+=f[i][j];
            if(abs(s[i+1]-s[i])<2) break;
            if(i==1) ans+=1;
        }
        return ans;
    }
    
    int main()
    {
        cin>>A>>B;
        DP();
        cout<<solve(B)-solve(A-1);
    }
    蒟蒻的代码,大佬别点开
  • 相关阅读:
    MySQL-基本sql命令
    Java for LeetCode 203 Remove Linked List Elements
    Java for LeetCode 202 Happy Number
    Java for LeetCode 201 Bitwise AND of Numbers Range
    Java for LeetCode 200 Number of Islands
    Java for LeetCode 199 Binary Tree Right Side View
    Java for LeetCode 198 House Robber
    Java for LeetCode 191 Number of 1 Bits
    Java for LeetCode 190 Reverse Bits
    Java for LeetCode 189 Rotate Array
  • 原文地址:https://www.cnblogs.com/zzzyc/p/8780173.html
Copyright © 2011-2022 走看看