1 条题解
-
0
自动搬运
来自洛谷,原作者为

EuphoricStar
Remember.搬运于
2025-08-24 21:37:17,当前版本为作者最后更新于2021-09-11 10:33:53,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路
比较套路的区间 DP。
设 为区间 最短可以压缩到的长度,则转移方程为:
这个比较好理解,就是将 和 两段已经压缩到最短的字符串直接拼在一起。
- $f_{i,j}=\min\limits_{k=1}^{j-i}f_{i,i+k-1}+2+\operatorname{digit}(\frac{j-i+1}{k})$( 是 的因数且 是 的一个周期)
这个也不是很难想,因为是周期,所以可以压缩,长度即为 可以压缩到的最短长度加上两个括号再加上 的位数( 表示这个周期连续出现的次数)。
由于题目还要求输出方案,所以用 记录 最短可以压缩到的字符串,当发现有更优决策时更新 即可。
边界条件为:,。
代码
#include <bits/stdc++.h> using namespace std; int n, f[110][110]; string s, ans[110][110]; int digit(int x) { int res = 0; while (x) { ++res; x /= 10; } return res; } string int2str(int x) { stringstream ss; ss << x; return ss.str(); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> s; n = s.size(); s = ' ' + s; memset(f, 0x3f, sizeof(f)); for (int i = 1; i <= n; ++i) { for (int j = i; j <= n; ++j) { ans[i][j] = ""; } } for (int i = 1; i <= n; ++i) { f[i][i] = 1; ans[i][i] = s[i]; } for (int p = 2; p <= n; ++p) { for (int i = 1, j = p; j <= n; ++i, ++j) { for (int k = i; k < j; ++k) { if (f[i][j] > f[i][k] + f[k + 1][j]) { f[i][j] = f[i][k] + f[k + 1][j]; ans[i][j] = ans[i][k] + ans[k + 1][j]; } } for (int k = 1; k < p; ++k) { if (p % k) { continue; } bool flag = 1; for (int l = k; l + i <= j; ++l) { if (s[l + i] != s[l % k + i]) { flag = 0; break; } } if (flag) { if (f[i][j] > f[i][i + k - 1] + 2 + digit(p / k)) { f[i][j] = f[i][i + k - 1] + 2 + digit(p / k); ans[i][j] = int2str(p / k) + '(' + ans[i][i + k - 1] + ')'; } } } } } cout << ans[1][n] << endl; return 0; }
- 1
信息
- ID
- 1427
- 时间
- 500ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者