洛谷P1415 拆分数列

https://www.luogu.org/problemnew/show/P1415

不会。。

看洛谷题解吧。。

自己的理解:标程做法是:先做一遍dp求出最后一个数开始位置的最大值p,那么就相当于最后一个逗号必须加在p位置左侧;然后反着dp一遍,求出dp[i]表示T(i,n)划分结果中使得第一个数最大时第一个数最大的结束位置(dp[p]=n,dp[p前面连续一段0]=n(否则这一小段0会给出有问题的答案;这么做是没有问题的,因为如果p前面全部是0那么可以发现没有问题,p前面还有非0那么不可能这些0单独成一段;再前面就不用特判了,因为一定存在<p的答案),且结束位置有边界<p);最后一步贪心确定答案,每一次都取当前能取的最大数

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pii;
13 char s[510];
14 int n;
15 int c1(int l1,int r1,int l2,int r2)
16 {
17     for(;l1<=r1&&s[l1]=='0';++l1);
18     for(;l2<=r2&&s[l2]=='0';++l2);
19     if(r1-l1!=r2-l2)    return r1-l1<r2-l2?-1:1;
20     else    return strncmp(s+l1,s+l2,r1-l1+1);
21 }
22 int f[510];
23 int main()
24 {
25     int i,j,p;
26     scanf("%s",s+1);n=strlen(s+1);
27     for(i=1;i<=n;++i)
28     {
29         for(j=i;j>=2;--j)
30             if(c1(f[j-1],j-1,j,i)<0)
31             {
32                 f[i]=j;
33                 goto xx1;
34             }
35         f[i]=1;
36 xx1:;
37     }
38     //printf("2t%d %d %d
",i,f[0],f[1]);
39     p=f[n];
40     f[p]=n;
41     for(i=p-1;i>=1&&s[i]=='0';--i)    f[i]=n;
42     for(;i>=1;--i)
43     {
44         for(j=p-1;j>=i;--j)
45             if(c1(i,j,j+1,f[j+1])<0)
46             {
47                 f[i]=j;
48                 break;
49             }
50     }
51     for(i=1;i<=n;i=f[i]+1)
52     {
53         //printf("1t%d
",f[i]);
54         for(j=i;j<=f[i];++j)
55             putchar(s[j]);
56         if(f[i]!=n)    putchar(',');
57         //scanf("%d",new int);
58     }
59     return 0;
60 }
View Code
原文地址:https://www.cnblogs.com/hehe54321/p/9919142.html