题目大意
给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。
题解
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 510;
int A[MAX_N];
int F1[MAX_N], F2[MAX_N], AnsF2[MAX_N];
int N;
void CharToA(char *s)
{
N = strlen(s + 1);
for (int i = 1; i <= N; i++)
A[i] = s[i] - '0';
}
bool RangeLt(int l1, int r1, int l2, int r2)
{
while (A[l1] == 0 && l1 <= r1)
l1++;
while (A[l2] == 0 && l2 <= r2)
l2++;
if (r1 - l1 != r2 - l2)
return r1 - l1 < r2 - l2;
else
for (int i = 0; i <= r1 - l1; i++)
if (A[l1 + i] != A[l2 + i])
return A[l1 + i] < A[l2 + i];
return false;
}
void DP1()
{
for (int i = 1; i <= N; i++)
F1[i] = 1;
for (int i = 1; i <= N; i++)
for (int j = 2; j <= i; j++)
if (RangeLt(F1[j - 1], j - 1, j, i))
F1[i] = j;
}
void DP2(int ed)
{
memset(F2, 0, sizeof(F2));
F2[ed] = N;
for (int i = ed - 1; i >= 1; i--)
for (int j = i; j <= ed - 1; j++)
if (RangeLt(i, j, j + 1, F2[j + 1]))
F2[i] = j;
}
bool CmpF2()
{
int cur = 1;
while (cur <= N)
{
if (F2[cur] != AnsF2[cur])
return F2[cur] > AnsF2[cur];
cur = F2[cur] + 1;
}
return false;
}
void Print()
{
int cur = 1;
bool tag = false;
while (cur <= N)
{
if (tag)
putchar(',');
tag = true;
for (int i = cur; i <= AnsF2[cur]; i++)
putchar('0' + A[i]);
cur = AnsF2[cur] + 1;
}
}
int main()
{
char s[MAX_N];
scanf("%s", s + 1);
CharToA(s);
DP1();
DP2(F1[N]);
memcpy(AnsF2, F2, sizeof(F2));
for (int i = F1[N] - 1; A[i] == 0; i--)
{
if (!RangeLt(F1[i - 1], i - 1, i, N))
break;
DP2(i);
if (CmpF2())
memcpy(AnsF2, F2, sizeof(F2));
}
Print();
return 0;
}