• 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 }
  • 相关阅读:
    个人学习jQuery笔记
    (转载) jQuery页面加载初始化的3种方法
    [转]学会和同事相处的30个原则
    解决iis出现这个问题-2147467259 (0x80004005)
    不规则瀑布流图片墙
    实现图片大小的自动控制( 图片大小控制CSS代码)
    (转载)DataTable使用技巧总结
    (转载) jQuery 页面加载初始化的方法有3种
    ajax连接数据库并操作数据库
    java Semaphore实现ABC三个线程循环打印
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7392518.html
Copyright © 2020-2023  润新知