题目链接:
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; }