hdu 3565 Bi-peak Number 數位dp
阿新 • • 發佈:2019-02-11
題目連結:
題目大意:
各位數字先增後減的數稱為峰值數(位數大於等3且第一位非零),然後兩個峰值數連在一起是一個bi-peak數,求兩個數之間bi-peak數的各位數字之和的最大值。
解題思路:
數位dp,dp[i][j][k]表示當前後面還有i位,j表示前一位的數字,k表示與峰值的狀態關係。
k=0 表示前面的為零,k=1表示前面恰好有一個在第一個波峰的上坡上,k=2表示前面至少有兩個在第一個波峰的上坡上,k=3表示在第一個波峰的下坡上
k=4表示前面恰好有一個在第二個波峰的上坡上,k=5表示前面至少有兩個在第二個波峰的上坡上,k=6表示在第二個波峰的下坡上
注意峰值數的位數至少為3並且第一位非零。
程式碼:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
using namespace std;
#define ll unsigned __int64
int dp[30][15][7];
//狀態0表示前面都是0,狀態1表示第一個上坡後面不能下坡,2表示第一個上坡後面可以是下坡,3表示第一個下坡
// 4 二 5 二 6 二
int aa[30],bb[30];
int dfs(int cur,int last,int flag,int aflag,int bflag)
{
if(!cur) //到了最後一位
return (flag==6)?0:-1;
if(!aflag&&!bflag&&dp[cur][last][flag]!=-1)
return dp[cur][last][flag];
int Min=aflag?aa[cur]:0; //下界
int Max=bflag?bb[cur]:9; //上界
int res=-1;
for(int i=Min;i<=Max;i++)
{
int status=0;
if(flag==0&&i)
status=1;
else if(flag==1)
{
if(i>last)
status=2;
else
status=-1;
}
else if(flag==2)
{
if(i<last)
status=3;
else if(i==last)
status=-1;
else
status=2;
}
else if(flag==3)
{
if(i>last)
status=4;
else if(i==last)
{
if(i)
status=4;
else
status=-1;
}
else
status=3;
}
else if(flag==4)
{
if(i>last)
status=5;
else
status=-1;
}
else if(flag==5)
{
if(i<last)
status=6;
else if(i==last)
status=-1;
else
status=5;
}
else if(flag==6)
{
if(i<last)
status=6;
else
status=-1;
}
if(status!=-1)
{
int temp=dfs(cur-1,i,status,aflag&&i==Min,bflag&&i==Max);
if(temp!=-1)
res=max(res,i+temp);
}
}
if(!aflag&&!bflag)
dp[cur][last][flag]=res;
return res;
}
int main()
{
int t;
scanf("%d",&t);
memset(dp,-1,sizeof(dp));
for(int ca=1;ca<=t;ca++)
{
ll a,b;
scanf("%I64u%I64u",&a,&b);
int pos=0;
while(b)
{
++pos;
aa[pos]=a%10;
a/=10;
bb[pos]=b%10;
b/=10;
}
int ans=dfs(pos,0,0,1,1);
printf("Case %d: ",ca);
if(ans!=-1)
printf("%d\n",ans);
else
printf("0\n");
}
return 0;
}