zoukankan      html  css  js  c++  java
  • HDOJ 3565 Bipeak Number (数位DP)

    Problem Description:
    A peak number is defined as continuous digits {D0, D1 … Dn-1} (D0 > 0 and n >= 3), which exist Dm (0 < m < n - 1) satisfied Di-1 < Di (0 < i <= m) and Di > Di+1 (m <= i < n - 1).
    A number is called bi-peak if it is a concatenation of two peak numbers.



    The score of a number is the sum of all digits. Love8909 is crazy about bi-peak numbers. Please help him to calculate the MAXIMUM score of the Bi-peak Number in the closed interval [A, B].
     
    分析:由于结果不满足区间减法,所以不能像通常那样计算cal(b)-cal(a-1),正确的处理方法是,在dfs时保存2个标记,一个标记前缀是否达上界,另一个标记是否达下界。然后就是状态分析了,分析清楚了也就简单了,以下是我设计的状态:
    s=0:前导0的状态;
    s=1:第一个山峰的上坡,且不能立马下坡;
    s=2:第一个山峰的上坡,且最后一点能看成是最高点,下一个点可以是下坡;
    s=3:第一个山峰的下坡;
    s=4:第二个山峰的上坡,且不能立马下坡;
    s=5:第二个山峰的上坡,且最后一点能看成是最高点,下一个点可以是下坡;
    s=6:第二个山峰的下坡;
    s=-1:其余不合法的状态。
    View Code
    #include <stdio.h>
    #include <string.h>
    #define MAX(a,b) ((a)>(b)?(a):(b))
    #define N 20
    #define INF 0x7f7f7f7f
    typedef unsigned __int64 LL;
    int sx[N],sy[N];
    int dp[N][10][7];
    int dfs(int pos,int last,int s,int fx,int fy)
    {
        if(pos==-1) return s==6?0:-1;
        if(!fx&&!fy&&dp[pos][last][s]!=INF)    return dp[pos][last][s];
        int min=fx?sx[pos]:0;
        int max=fy?sy[pos]:9;
        int ret=-1;
        for(int i=min;i<=max;i++)
        {
            int ns=s;
            if(s==0 && i)  ns=1;
            else if(s==1)
            {
                if(i>last)  ns=2;
                else    ns=-1;
            }
            else if(s==2)
            {
                if(i<last)  ns=3;
                else if(i==last)    ns=-1;
            }
            else if(s==3 && i>=last)
            {
                if(i)   ns=4;
                else    ns=-1;
            }
            else if(s==4)
            {
                if(i>last)  ns=5;
                else    ns=-1;
            }
            else if(s==5)
            {
                if(i<last)  ns=6;
                else if(i==last)    ns=-1;
            }
            else if(s==6 && i>=last) ns=-1;
            if(ns!=-1)
            {
                int tmp=dfs(pos-1,i,ns,fx&&i==min,fy&&i==max);
                if(tmp!=-1) ret=MAX(ret,i+tmp);
            }
        }
        if(!fx&&!fy)  dp[pos][last][s]=ret;
        return ret;
    }
    int main()
    {
        int t,kase=0;
        memset(dp,0x7f,sizeof(dp));
        scanf("%d",&t);
        while(t--)
        {
            printf("Case %d: ",++kase);
            LL x,y;
            scanf("%I64u%I64u",&x,&y);
            int pos=0;
            for(;y;x/=10,y/=10) sx[pos]=x%10,sy[pos++]=y%10;
            int ans=dfs(pos-1,0,0,1,1);
            if(ans==-1) ans=0;
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    优麒麟(UbuntuKylin)不是国产Linux操作系统
    Win10開始菜单打不开
    五步让你玩转CocoaPods
    设计模式学习笔记之适配器模式
    感谢各位亲们的大力支持,免费的HTML5学习课程《HTML5网页开发实例具体解释》连载已经结束了!
    iOS获取时间、日期
    leetcode NO.1 两数之和 (python3实现)
    leetcode NO.53 最大子序列和 (python3实现)
    [笔记]《算法图解》第六章 广度搜索优先
    [笔记]《算法图解》第四章 快速排序
  • 原文地址:https://www.cnblogs.com/algorithms/p/2669727.html
Copyright © 2011-2022 走看看