zoukankan      html  css  js  c++  java
  • HDU 3565 Bi-peak Number(数位DP)题解

    题意:我们定义每一位先严格递增(第一位不为0)后严格递减的数为峰(比如1231),一个数由两个峰组成称为双峰,一个双峰的价值为每一位位数和,问L~R双峰最大价值

    思路:数位DP。显然这个问题和pos有关,和前一项有关,和当前状态有关,我们定义dp[i][j][k]第i位前面j状态k的后面的最佳情况。

    状态有7种:

    0什么都没,1刚开始第一个上坡,2已经第一个上坡了可以转折了,3第一个下坡0
    4刚开始第二个上坡,5已经第二个上坡可以转折了,6第二个下坡

    然后数位DP一下就好了。

    注意,要开ull,30多个wa的教训

    代码:

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 10000 + 10;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    int dp[30][10][10];
    //0什么都没,1刚开始第一个上坡,2已经第一个上坡了,3第一个下坡0
    //4刚开始第二个上坡,5已经第二个上坡,6第二个下坡
    //第i位前面j状态k的后面的最佳情况
    int top[30], low[30];
    int dfs(int pos, int pre, int st, bool MAXflag, bool MINflag){
        if(pos == -1)
            return st == 6? 0 : -INF;
        if(!MINflag && !MAXflag && dp[pos][pre][st] != -1)
            return dp[pos][pre][st];
        int Min = MINflag? low[pos] : 0;
        int Max = MAXflag? top[pos] : 9;
        int ans = -INF;
        for(int i = Min; i <= Max; i++){
            int newSt;
            if(st == 0){
                if(i == 0) newSt = 0;
                else newSt = 1;
            }
            else if(st == 1){
                if(i <= pre) continue;
                if(i > pre) newSt = 2;
            }
            else if(st == 2){
                if(i == pre) continue;
                if(i < pre) newSt = 3;
                else newSt = 2;
            }
            else if(st == 3){
                if(i < pre) newSt = 3;
                else if(i > pre) newSt = 4;
                else{
                    if(i) newSt = 4;
                    else continue;
                }
            }
            else if(st == 4){
                if(i <= pre) continue;
                newSt = 5;
            }
            else if(st == 5){
                if(i == pre) continue;
                if(i > pre) newSt = 5;
                else newSt = 6;
            }
            else if(st == 6){
                if(i >= pre) continue;
                newSt = 6;
            }
            ans = max(ans, i + dfs(pos - 1, i, newSt, MAXflag && i == Max, MINflag && i == Min));
        }
        if(!MAXflag && !MINflag)
            dp[pos][pre][st] = ans;
        return ans;
    }
    int solve(ull l, ull r){
        int pos = 0;
        while(r){
            top[pos] = r % 10;
            low[pos++] = l % 10;
            r /= 10;
            l /= 10;
        }
        int ans = dfs(pos - 1, 0, 0, true, true);
        return max(0, ans);
    }
    int main(){
        int t, ca = 1;
        memset(dp, -1, sizeof(dp));
        scanf("%d", &t);
        while(t--){
            ull l, r;
            cin >> l >> r;
            printf("Case %d: %d
    ", ca++, solve(l, r));
        }
        return 0;
    }
  • 相关阅读:
    顺序队列的模板
    链式队列模板
    链式栈模板
    栈应用hanoi
    判断出栈顺序
    用栈实现四则运算
    两栈共享问题
    The Preliminary Contest for ICPC Asia Nanjing 2019
    Educational Codeforces Round 71 (Rated for Div. 2)
    HDU6583:Typewriter(dp+后缀自动机)
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10727197.html
Copyright © 2011-2022 走看看