现在的位置: 首页 > 综合 > 正文

hdu 3565 Bi-peak Number 数位dp

2013年11月02日 ⁄ 综合 ⁄ 共 1850字 ⁄ 字号 评论关闭


题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3565


题目大意:

各位数字先增后减的数称为峰值数(位数大于等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;
}



抱歉!评论已关闭.