首页 > 代码库 > luoguP1415 拆分数列 [dp]
luoguP1415 拆分数列 [dp]
题目描述
给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。
输入输出格式
输入格式:
共一行,为初始的数字。
输出格式:
共一行,为拆分之后的数列。每个数之间用逗号分隔。行尾无逗号。
输入输出样例
输入样例#1:
[1]3456[2]3546[3]3526[4]0001[5]100000101
输出样例#1:
[1]3,4,5,6[2]35,46[3]3,5,26[4]0001[5]100,000101
说明
【题目来源】
lzn改编
【数据范围】
对于10%的数据,输入长度<=5
对于30%的数据,输入长度<=15
对于50%的数据,输入长度<=50
对于100%的数据,输入长度<=500
《拆分数列》解题报告
By lzn 动态规划常规题。
第一步先求出最后的那个数最小为多少。(为了叙述方便,记T(i,j)表示从原数列下标i取到j的数字组成的数。)只需正向dp一次,dp1[i]表示前i个数字分成任意多个递增数且最后的数最小时,最后的数为T(dp1[i],i)。则dp1[i]=max(j),(T(dp1[j-1],j-1)<T(j,i))。
第二步要求最后一个数确定的情况下,前面的数字按字典序尽量大的解。类似上面的方法反向动归一次即可。
算法复杂度o(l^3)。由于数据大部分为随机,实际运行效率接近l^2。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<string> 5 using namespace std; 6 7 const int maxn=505; 8 9 string str;10 int a[maxn],n,dP[maxn],Dp[maxn];11 12 bool cmp(int l1,int r1,int l2,int r2){13 while(l1<=r1&&a[l1]==0) l1++;14 while(l2<=r2&&a[l2]==0) l2++;15 int le1=r1-l1+1,le2=r2-l2+1;16 if(le1==0||le2==0) return 0;17 if(le1!=le2) return le1<le2;18 for(int i=0;i<le1;i++)19 if(a[l1+i]!=a[l2+i]) return a[l1+i]<a[l2+i];20 return 0;21 }22 23 //dP[i]=max(j),(T(dP[j-1],j-1)<T(j,i))24 void DP1(){25 for(int i=1;i<=n;i++){26 dP[i]=1;27 for(int j=i;j;j--)28 if(cmp(dP[j-1],j-1,j,i)){29 dP[i]=j;30 break;31 }32 // printf("dP[%d] = %d\n",i,dP[i]);33 }34 }35 36 //Dp[i]=max(j) (T(i,j)<T(j+1,f[j+1]))37 void DP2(){38 Dp[dP[n]]=n;39 for(int i=dP[n];a[i-1]==0;i--) Dp[i-1]=n;40 41 for(int i=dP[n]-1;i;i--){42 for(int j=dP[n]-1;j>=i;j--)43 if(cmp(i,j,j+1,Dp[j+1])){44 Dp[i]=j;45 break;46 }47 // printf("Dp[%d] = %d\n",i,Dp[i]);48 }49 }50 51 void print(int l,int r){52 for(int i=l;i<=r;i++)53 putchar(a[i]+‘0‘);54 }55 56 void print(){57 print(1,Dp[1]);58 int pos=Dp[1]+1;59 while(pos<=n){60 putchar(‘,‘);61 print(pos,Dp[pos]);62 pos=Dp[pos]+1;63 }64 }65 66 int main(){67 cin>>str; n=str.length();68 for(int i=0;i<n;i++) a[i+1]=str[i]-‘0‘;69 DP1(); DP2();70 print();71 return 0;72 }
luoguP1415 拆分数列 [dp]
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。