hdu3565 Bi-peak 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].
 

Input
The first line of the input is an integer T (T <= 1000), which stands for the number of test cases you need to solve.
Each case consists of two integers “A B” (without quotes) (0 <= A <= B < 2^64) in a single line.
 

Output
For the kth case, output “Case k: v” in a single line where v is the maximum score. If no bi-peak number exists, output 0.
 

Sample Input
  
  
3 12121 12121 120010 120010 121121 121121
 

Sample Output
  
  
Case 1: 0 Case 2: 0 Case 3: 8
题意:定义"特殊数"为两次先上升后下降形成的数,且第一位大于等于0,没有前导零,问所有满足条件的数中,位数和最大的是多少。
思路:可以把两座山峰看做7个状态,0:还没有到第一个山的上坡 1:到了第一个山的上坡,但是还不能“转弯”,即不能向下折,后面也类似 2:任然是第一个山的山坡,但是可以“转弯” 3:到了第一个山坡的下坡,且可以“转弯” 4:到了第二个山的上坡,但是还不能“转弯” 5:到了第二个山的的上坡,且可以转弯 6:到了第二个山的下坡。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 99999999
#define MOD 1000000007
int wei1[100],wei2[100];
int dp[100][10][8];

int dfs(int pos,int pre,int state,int flag1,int flag2)
{
    int i,j;
    if(pos==0){
        if(state==6)return 0;
        return -inf;
    }
    if(!flag1 && !flag2 && dp[pos][pre][state]!=-1){
        return dp[pos][pre][state];
    }
    int min1=flag1?wei1[pos]:0;
    int max1=flag2?wei2[pos]:9;
    int ans=-inf;
    for(i=min1;i<=max1;i++){
        if(state==0){
            if(i>0){
                ans=max(ans,i+dfs(pos-1,i,1,flag1&&i==min1,flag2&&i==max1) );
            }
            else if(i==0)ans=max(ans,0+dfs(pos-1,i,0,flag1&&i==min1,flag2&&i==max1));
        }
        else if(state==1){
            if(i>pre){
                ans=max(ans,i+dfs(pos-1,i,2,flag1&&i==min1,flag2&&i==max1));
            }
        }
        else if(state==2){
            if(i>pre){
                ans=max(ans,i+dfs(pos-1,i,2,flag1&&i==min1,flag2&&i==max1));
            }
            if(i<pre){
                ans=max(ans,i+dfs(pos-1,i,3,flag1&&i==min1,flag2&&i==max1 ) );
            }
        }

        else if(state==3){
            if(i<pre){
                ans=max(ans,i+dfs(pos-1,i,3,flag1&&i==min1,flag2&&i==max1 ) );
            }
            if(i>0){
                ans=max(ans,i+dfs(pos-1,i,4,flag1&&i==min1,flag2&&i==max1 ) );
            }

        }
        else if(state==4){
            if(i>pre){
                ans=max(ans,i+dfs(pos-1,i,5,flag1&&i==min1,flag2&&i==max1));
            }
        }
        else if(state==5){
            if(i>pre){
                ans=max(ans,i+dfs(pos-1,i,5,flag1&&i==min1,flag2&&i==max1));
            }
            if(i<pre){
                ans=max(ans,i+dfs(pos-1,i,6,flag1&&i==min1,flag2&&i==max1 ) );
            }

        }
        else if(state==6){
            if(i<pre){
                ans=max(ans,i+dfs(pos-1,i,6,flag1&&i==min1,flag2&&i==max1) );
            }
        }
    }
    if(!flag1 && !flag2){
        dp[pos][pre][state]=ans;
    }
    return ans;
}

int main()
{
    ull m,n;
    int T,i,j,cas=0;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&T);
    while(T--)
    {
        cin>>m>>n;
        int len=0;
        while(n){
            len++;
            wei2[len]=n%10;
            n/=10;
            wei1[len]=m%10;
            m/=10;
        }
        int ans=dfs(len,0,0,1,1);
        if(ans<0)ans=0;
        printf("Case %d: %d\n",++cas,ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值