题目大意
给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数。如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小;如果有多组解,则使得第一个数尽量大;如果仍有多组解,则使得第二个数尽量大,依次类推……)。
题解
#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; }