zoukankan      html  css  js  c++  java
  • hdu 6148 Valley Numer (数位dp)

    Problem Description
    众所周知,度度熊非常喜欢数字。

    它最近发明了一种新的数字:Valley Number,像山谷一样的数字。
    当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。
    比如,1,10,12,212,32122都是 Valley Number。
    121,12331,21212则不是。
    度度熊想知道不大于N的Valley Number数有多少。
    注意,前导0是不合法的。
     
    Input
    第一行为T,表示输入数据组数。
    每组数据包含一个数N。
    ● 1≤T≤200
    ● 1≤length(N)≤100
    Output
    对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。
    Sample Input
    3
    3
    14
    120
    Sample Output
    3
    14
    119
     
    题意:让你统计小于n的满足各个数位上不会出现先上升再下降的数字的个数
    一道基本的数位dp
    代码如下:
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 110;
     5 const ll mod = 1e9+7;
     6 char s[maxn];
     7 int dig[maxn];
     8 ll dp[110][10][2];
     9 ll dfs (int pos,int now,int up,int limit,int lead)//pos代表当前位 now代表上一位的数字 up=1表示到该位是上升状态
    10                                                   //limit=1表示前几位贴着n的上界 lead=1表示当前状态有前导零
    11 {
    12     if (pos<0){         //如果dp到了最低位
    13         if (lead) return 0; //如果当前结果是含有前导零的不计数
    14         else return 1;  //否则计数
    15     }
    16     if (!limit&&!lead&&dp[pos][now][up]!=-1)    //如果当前的dp状态没有到达给的数的上界
    17                                                 //而且,当前状态没有前导零而且之前计算过
    18         return dp[pos][now][up];                //记忆化搜索直接返回
    19     ll ans = 0;
    20     int top;    //当前位能达到的最大值
    21     if (limit) top = dig[pos];  //如果之前几位都达到了给的n的对应位的上限,此时这一位最大值就是n的pos位
    22     else top = 9;               //如果前面几位没有贴着n的上界,那么这一位不管整个数怎么取都不会大于n,自然这一位最大值为9
    23     for (int i=0;i<=top;++i){   //
    24         if (up&&i<now) continue;    //如果之前的up为上升状态而这一位比上一位小不满足题意直接过掉
    25         int nxtup;  //下一步up的状态
    26         if (up||((i>now)&&(!lead))) //下一步是上升状态有两种情况 1.前几位已经是上升的了
    27                                     //注意到这里已经保证如果up==1,那么此时i>=now
    28                                     //2.这一位比上一位大而且上一位还不是0(前导零,比如002这样是不算上升的)
    29         nxtup=1;                    //满足上面2个条件的任意一个的话下一步就是上升状态的
    30         else nxtup=0;//否则下一步上升up为0
    31         int nxtlead;    //下一步前导零的状态
    32         if ((i==0)&&lead) nxtlead = 1;//当且仅当前几位有前导零而且这一位i还是0,下一步还是有前导零的
    33         else nxtlead = 0;   //否则下一位就没有前导零
    34         int nxtlimit;   //下一步上界的状态
    35         if (limit&&i==dig[pos]) nxtlimit = 1;//当且仅当前几位一直贴着n的上界而且这一位还是贴着n的上界,此时下一步状态还是贴着上界
    36         else nxtlimit = 0;//否则下一步就不贴着n的上界了
    37         (ans+=(dfs(pos-1,i,nxtup,nxtlimit,nxtlead)))%=mod;//向下dp一位
    38     }
    39     if (!limit&&!lead)  //如果当前没到达边界而且没有前导零,这样的是有资格存进dp数组的
    40                         //因为dp[pos][now][up]存的是到pos位,当前数字为now,上升状态为up,没有到达上界而且没有前导零的数目
    41         return dp[pos][now][up]=ans;
    42     return ans;//如果没有资格直接返回答案计数就行了
    43 }
    44 int main()
    45 {
    46     int T;
    47     //freopen("de.txt","r",stdin);
    48     scanf("%d",&T);
    49     memset(dp,-1,sizeof dp);
    50     while (T--){
    51         scanf("%s",s);
    52         int len = strlen(s);
    53         for (int i=0;i<len;++i)
    54             dig[i]=s[i]-'0';
    55         reverse(dig,dig+len);
    56         cout<<dfs(len-1,0,0,1,1)<<endl;
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    PHP 开发 APP 接口 学习笔记与总结
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7392518.html
Copyright © 2011-2022 走看看