题目链接:HDOJ3565
题意:首先定义了一个peak number,是没有前导0的,存在某一个数位,比左右两边的数字都大的数
然后Bi-peak number,是两个peak number的数位相连
分析样例就能够得到这个题的坑点,很友善的题
样例1是只有5个数位,要分成Bi-peak number,至少要6位,abcdef,其中b>a,b>c,e>d,e>f
样例2是想要分解的话,后面那个数有前导0
样例3简单
这个题充分的体现了自己数位DP不熟练
不会根据题目,来灵活的设计DP状态和转移
dp【pos】【state】【pre】是设计的状态
pos和pre很好理解,那么state如何定义呢?
因为是Bi-peak,所以需要标记我当前找的这个数处在那个阶段,是往第一个peak走,还是从第二个peak下来,都需要记录
所以:
0表示前导0
1表示第一个上升坡
2表示第一个顶点
3表示第一个下降坡
4表示第二个上升坡
5表示第二个顶点
6表示第二个下降坡
这个题是求最大值,不是求区间个数
所以不会满足区间的减法
所以用到一个新的技巧,把【X,Y】区间中的两端X,Y都数位分解放到dfs中去
记录两个变量,分别是前导的0和后置的flag
每次在数位枚举的时候,从可用的最小枚举到可用的最大
状态转移只能严格的从前一个转到后一个,因为必须按照数位的大小来排
特殊情况就是可以浪费如:123212321
可以上坡下坡时间长一点,数位多一点,这就是在山上多一个判断
细节见代码
#include<map>
#include<set>
#include<math.h>
#include<time.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define ll rt<<1
#define rr rt<<1|1
#define LL long long
#define ULL unsigned long long
#define maxn 1050
#define maxnum 1000050
#define eps 1e-6
#define input freopen("input.txt","r",stdin)
#define output freopen("output.txt","w",stdout)
#define MOD 1000000007
bool vis[25][10][15];
int dp[25][10][15];
int digitlow[25],digitup[25];
int dfs(int pos,int state,int pre,bool lowbound,bool upbound){
if (state==0&&pos<6) return -1;
if (pos==0) return state==5?0:-1;
if (lowbound&&upbound&&vis[pos][state][pre])
return dp[pos][state][pre];
int Min=lowbound?0:digitlow[pos];
int Max=upbound?9:digitup[pos];
int ret=-1,temp;
for(int i=Min;i<=Max;i++)
switch(state){
case 0:temp=dfs(pos-1,(i==0?0:1),i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
break;
case 1:
if (i>pre){
temp=dfs(pos-1,1,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
temp=dfs(pos-1,2,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
break;
case 2:
if (i<pre){
temp=dfs(pos-1,3,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
break;
case 3:
if (i<pre){
temp=dfs(pos-1,3,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
if (i){
temp=dfs(pos-1,4,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
break;
case 4:
if (i>pre){
temp=dfs(pos-1,4,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
temp=dfs(pos-1,5,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
break;
case 5:
if (i<pre){
temp=dfs(pos-1,5,i,lowbound||i>Min,upbound||i<Max);
if (temp!=-1)
ret=max(ret,temp+i);
}
break;
}
if (lowbound&&upbound){
vis[pos][state][pre]=true;
dp[pos][state][pre]=ret;
}
return ret;
}
int calc(unsigned long long x,unsigned long long y){
memset(digitlow,0,sizeof(digitlow));
memset(digitup,0,sizeof(digitup));
int len1=0,len2=0;
while(x){
digitlow[++len1]=x%10;
x/=10;
}
while(y){
digitup[++len2]=y%10;
y/=10;
}
return dfs(len2,0,0,0,0);
}
int main(){
//input;
int T;
unsigned long long x,y;
scanf("%d",&T);
for(int Case=1;Case<=T;Case++){
scanf("%I64u%I64u",&x,&y);
int ans=calc(x,y);
printf("Case %d: %d\n",Case,ans==-1?0:ans);
}
return 0;
}