• 【数位dp】山峰数


    【数位dp】 山峰数

    题目来源:5月1日第一次dp考试T2

    >>>>题目

    【题目描述】

    山峰数是指数字排列中不存在山谷(先降后升)的数,例如0,5,13,12321都是山峰数,101,1110000111都不是山峰数。
    现给出n个数,请依次判断它们是否为山峰数,如果不是,输出-1。如果是,求出比它小的数中有多少个山峰数。

    【输入格式】

    第一行一个数n,表示询问数目。
    接下来n行,每一行一个数x,表示询问的数。

    【输出格式】

    输出有n行,x如果不是山峰数,输出-1。x如果是山峰数,则输出有多少个比它小的山峰数。

    【输入样例】

    5
    10
    55
    101
    1000
    1234321

    【输出样例】

    10
    55
    -1
    715
    94708

    【数据范围】

    20% 数据满足x ≤ 1e6。
    100% 数据满足n ≤ 10, x ≤ 1e60

    >>>>代码

    啊因为我不知道应该分析什么……就是dfs版的数位dp

    直接看代码好啦

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll f[62][10][2][2];//f[i][j][k][p]:第i位上一个数是j,是否是上升期,是否压上界 的方案数 (其中是和否分别用1和0表示) 
    int len,T,a[62];
    char s[65];
    ll dfs(int pos,int pre,int isdown,int lim)
    {//   现在的位置  上一个数  是否是下降期  是否压上界 
        if(pos==len+1) return 1;//返回一种可行的方案数 
        if(f[pos][pre][isdown][lim]!=-1) return f[pos][pre][isdown][lim];//记忆化搜索 
        int up=lim?a[pos]:9;//上界 
        ll tmp=0;
        for(int i=0;i<=up;++i)
        {
            if(!isdown)
            {
                if(i>=pre) tmp+=dfs(pos+1,i,0,i==up&&lim);//一定要这一位和上一位都压上界,下一位才压上界 
                else tmp+=dfs(pos+1,i,1,i==up&&lim);//从这里开始下降 
            }
            else if(i<=pre) tmp+=dfs(pos+1,i,1,i==up&&lim);
        }
        return f[pos][pre][isdown][lim]=tmp;
    }
    int main()
    {
        scanf("%d
    ",&T);
        while(T--)
        {
            scanf("%s",s+1);
            len=strlen(s+1);
            for(int i=1;i<=len;++i) a[i]=s[i]-'0';
            
            bool ishill=true,isdown=false;//ishill:是否是山峰数,isdown:是下降期 
            for(int i=2;i<=len;++i)
            {
                if(a[i]<a[i-1]) isdown=true;
                if(isdown&&a[i]>a[i-1])//判断是否是山峰数 
                {
                    ishill=false; 
                    break;
                }
            }
            if(!ishill) printf("-1
    ");
            else 
            {
                memset(f,-1,sizeof(f));
                printf("%I64d
    ",dfs(1,0,0,1)-1);//因为要求的是比它小的山峰数,所以要减一 
            }
        }
        return 0;
    } 
    /*
    5
    10
    55
    101
    1000
    1234321
    
    ->
    10
    55
    -1
    715
    94708
    */

    完结撒花✿✿ヽ(°▽°)ノ✿!!!

  • 相关阅读:
    POJ 1659 Frogs' Neighborhood (贪心)
    HDU 2544 最短路 (Floyd)
    CodeForces 632C Grandma Laura and Apples (模拟)
    CodeForces 731F Video Cards (数论+暴力)
    CodeForces 731C Socks (DFS或并查集)
    CodeForces 731B Coupons and Discounts (水题模拟)
    CodeForces 731A Night at the Museum (水题)
    UVaLive 6834 Shopping (贪心)
    zzuli 1484 继续双线
    zzuli 1875多线DP
  • 原文地址:https://www.cnblogs.com/psyyyyyy/p/10845224.html
Copyright © 2020-2023  润新知