简单dp hdu-4105-Electric wave

题目链接:

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

题目意思:

给一个字符串,求最大的分隔空格数,记所有被分隔的数为a1,a2,a3,.....

使得 a1<a2>a3<a4>a5.....

解题思路:

简单的dp;

记dp[0][i][j]表示从第i个字符开始到结束,且以第i~j个字符组成的数作为谷值的最大的分隔的数。

记dp[1][i][j]                          。。。                                                                   峰数....

则dp[0][i][j]=max(dp[0][i][j],dp[1][j+1][k]+1) // 其中(j+1~k)组成的数的值大于(i~j)组成的数。

    dp[1][i][j]=max(dp[1][i][j],dp[0][j+1][k]+1) // 其中(j+1~k)组成的数的值小于(i~j)组成的数。

注意:

1、有前置0,比较的时候消除前置0.

2、比较的时候用strcmp和strncpy超时,直接一位一位的比。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/

int dp[2][110][110]; //dp[0][i][j]表示从第i个字符开始长度为j的作为低谷时能分隔的最多数的个数
char save[110];
char temp1[110],temp2[110];

bool ismin(int i,int j,int k,int p)
{
   while(save[i]=='0')
      i++;
   while(save[k]=='0')
      k++;
   if(k>p)
      return false;
   if(i>j)
      return true;
   if(j-i<p-k)
      return true;
   else if(j-i>p-k)
      return false;
   else
   {
      for(int pp=0;pp<=j-i;pp++)
         if(save[pp+i]<save[pp+k])
            return true;
         else if(save[pp+i]>save[pp+k])
            return false;
   }
   return false;
}
bool Ismin(char * a,char * b) //用这里的函数,居然超时
{
   int len1=strlen(a),len2=strlen(b);
   int i=0,j=0;

   while(a[i]=='0')
      i++;
   while(a[j]=='0')
      j++;
   if(j>=len2)
      return false;
   if(i>=len1)
      return true;
   if(len1-i<len2-j)
      return true;
   else if(len1-i>len2-j)
      return false;
   else
   {
      if(strcmp(a+i,b+i)<0)
         return true;
      else
         return false;
   }
}
int main()
{
   int n;

   while(~scanf("%d",&n))
   {
      memset(dp,0,sizeof(dp));
      scanf("%s",save+1);
      for(int i=1;i<=n;i++) //初始化
      {
         dp[0][i][n]=1;
         dp[1][i][n]=1;
      }

      for(int i=n-1;i>=1;i--) //计算 dp[][i][j]
      {
         for(int j=i;j<n;j++)
         {
            //strncpy(temp1,save+i,j-i+1);
           // temp1[j-i+1]='';
           int k=j+1;
            for(int p=k;p<=n;p++)
            {
               //strncpy(temp2,save+k,p-k+1);
               //temp2[p-k+1]='';
              // printf("2:%s
",temp2);
               if(ismin(k,p,i,j)) //后面的小,说明当前可以作为峰值
                  dp[1][i][j]=max(dp[1][i][j],dp[0][k][p]+1);
               else if(ismin(i,j,k,p)) //后面的大,说明当前可以作为谷值
                  dp[0][i][j]=max(dp[0][i][j],dp[1][k][p]+1);
            }
            //printf("i:%d j:%d %d %d
",i,j,dp[0][i][j],dp[1][i][j]);
         }
      }
      int ans=0; //找到分隔多的数的个数
      for(int i=1;i<=n;i++)
         ans=max(ans,dp[0][1][i]);
      printf("%d
",ans-1); //隔板为分隔的数个数-1

   }
   return 0;
}


原文地址:https://www.cnblogs.com/riskyer/p/3241419.html