圆
圆
题目描述
给出一个圆,圆上等距分布 个点,编号为 。
另有 条线段,第 条线段的端点为 和 ,权重为 。
定义一个圆是优良的,当且仅当所有线段无交(端点重合也算相交)。
如上图,线段 与线段 相交,但是线段 与线段 不交。
若删掉一条边的代价为其权重,求让圆优良的最小代价。
输入描述:
第一行两个数 。接下来 行,每行三个数 ,描述一条线段。
注意线段可能重合。
输出描述:
输出为一个数,即最小代价。
示例1
输入
6 4
1 4 1
2 3 3
2 4 10
5 6 2
输出
4
备注:
对于所有数据,,,。
解题思路
来补一下这道题,当时卡了一个多小时才想到区间 dp 的做法,本来思路都是对的,结果初始化的时候不知道抽什么风搞得很复杂,最后 WA 到结束了都没做出来。
把圆上的线段看作区间,那么所有线段无交就等价于任意两个区间都不相交,但允许区间被完全包含(端点不能重合)。因此问题就变成了,删除若干个区间使得剩余的区间满足条件的最小代价。问题可以继续转换成,假设一开始没有区间,现在要在满足条件的前提下添加尽可能多的区间,求能添加的最大代价是多少。最后用所有区间的总代价减去这个值就是删除区间所需的最小代价。
如果要保留某个区间 ,那么所有选择的区间必须严格在 ,, 这些范围内。都是区间的形式因此可以考虑用区间 dp。
定义 表示只选择 范围内且满足条件的区间的所有方案中的最大代价。根据是否选择了左端点为 的区间来进行状态划分。如果不选择左端点为 的区间,那么状态转移方程就是 。如果选择左端点为 的区间,记 和 为对应区间的右端点和代价,只能选择 的区间,状态转移方程为 。
最后只需初始化所有的 为 。答案就是 。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10;
vector<array<int, 2>> g[N];
LL f[N][N];
int main() {
int n, m;
scanf("%d %d", &n, &m);
LL s = 0;
while (m--) {
int x, y, w;
scanf("%d %d %d", &x, &y, &w);
if (x > y) swap(x, y);
g[x].push_back({y, w});
s += w;
}
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
f[i][j] = f[i + 1][j];
for (auto &p : g[i]) {
if (p[0] <= j) f[i][j] = max(f[i][j], f[p[0] + 1][j] + f[i + 1][p[0] - 1] + p[1]);
}
}
}
printf("%lld", s - f[1][n]);
return 0;
}
参考资料
牛客练习赛122 官方题解:https://ac.nowcoder.com/discuss/1255860
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18053991
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-03-05 异或值
2022-03-05 聪明的燕姿