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

szh_AK_all
S挂分挂到被洛谷7级勾卡线|I can do all things搬运于
2025-08-24 23:07:20,当前版本为作者最后更新于2025-01-21 09:52:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
好玩的区间 dp。
竟然是这题题解区的第一篇题解诶。分析
根据套路,先设 表示删完区间 内的数可获得的最大权值。但是容易发现区间 还可能与 中的数有联系,因为可能在删完 的一个前缀 时, 与 可以拼接在一起,即 。
于是设 表示删完区间 内的数,且需要或不需要删掉 ( 为 或 ),如果要删的话则删 个的最大权值,接下来转移方程便很好推了。
枚举断点 ,则有两种转移:
-
当 且 时,可以选择先将区间 删完,再将区间 与区间 拼起来,答案即 。注意此时区间 是与外界隔绝的。
-
当 或者 时,考虑将区间 直接从 处断开。那么与 有联系的区间是 ,并且此时会产生 的权值,答案即为 。
细节:
-
答案应是所有可以转移到的 的最大值;
-
个人认为写记忆化搜索更方便点;
-
边界情况需要特判,即 时,权值为 (前提是 没有越界);
-
转移的开始可以有很多种,这里是用 及 作为转移的开始。
Code
#include <bits/stdc++.h> using namespace std; #define int long long int a[105], f[105][105][105][2], mi, ma, tmp, k; int dfs(int l, int r, int xuan, int p) { if (l > r) { if (xuan && (mi > xuan || xuan > ma)) return -1000000000; tmp = max(tmp, xuan * xuan); return xuan * xuan; } if (f[l][r][xuan][p] > k) return f[l][r][xuan][p]; if (xuan > ma) return 0; int ans = 0; for (int k = l; k <= r; k++) if (p && a[k] == a[l - 1]) ans = max(ans, dfs(l, k - 1, 0, 0) + dfs(k + 1, r, xuan + 1, 1)); for (int k = l; k <= r; k++) if ((!xuan || (mi <= xuan && xuan <= ma))) ans = max(ans, dfs(l, k - 1, 0, 0) + dfs(k + 1, r, 1, 1) + xuan * xuan); tmp = max(tmp, ans); return f[l][r][xuan][p] = ans; } signed main() { memset(f, -0x3f, sizeof(f)); k = f[0][0][0][0]; int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; cin >> mi >> ma; for (int i = 1; i <= n; i++) dfs(i + 1, n, 1, 1); tmp = max(tmp, dfs(1, n, 0, 0)); cout << tmp; } -
- 1
信息
- ID
- 11194
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者