题目描述

给出一个圆,圆上等距分布 n 个点,编号为 1n

另有 m  条线段,第 i 条线段的端点为 xi 和 ,权重为 wi

定义一个圆是优良的,当且仅当所有线段无交(端点重合也算相交)。

如上图,线段 {14}  与线段 {25},{34} 相交,但是线段 {25} 与线段 {34} 不交。

若删掉一条边的代价为其权重,求让圆优良的最小代价。

输入描述:

第一行两个数 n,m。接下来 m  行,每行三个数 x,y,w,描述一条线段。

注意线段可能重合。

输出描述:

输出为一个数,即最小代价。

示例1

输入

6 4
1 4 1
2 3 3
2 4 10
5 6 2

输出

4

备注:

对于所有数据,1n,m2×1030wi109xiyi

 

解题思路

  来补一下这道题,当时卡了一个多小时才想到区间 dp 的做法,本来思路都是对的,结果初始化的时候不知道抽什么风搞得很复杂,最后 WA 到结束了都没做出来。

  把圆上的线段看作区间,那么所有线段无交就等价于任意两个区间都不相交,但允许区间被完全包含(端点不能重合)。因此问题就变成了,删除若干个区间使得剩余的区间满足条件的最小代价。问题可以继续转换成,假设一开始没有区间,现在要在满足条件的前提下添加尽可能多的区间,求能添加的最大代价是多少。最后用所有区间的总代价减去这个值就是删除区间所需的最小代价。

  如果要保留某个区间 [l,r],那么所有选择的区间必须严格在 [l+1,r1][1,l1][r+1,n] 这些范围内。都是区间的形式因此可以考虑用区间 dp。

  定义 f(l,r) 表示只选择 [l,r] 范围内且满足条件的区间的所有方案中的最大代价。根据是否选择了左端点为 l 的区间来进行状态划分。如果不选择左端点为 l 的区间,那么状态转移方程就是 f(l,r)=f(l+1,r)。如果选择左端点为 l 的区间,记 yiwi 为对应区间的右端点和代价,只能选择 yir 的区间,状态转移方程为 f(l,r)=minyir{f(yi+1,r)+f(l+1,yi1)+wi}

  最后只需初始化所有的 f(l,r)0。答案就是 i=1mwif(1,n)

  AC 代码如下,时间复杂度为 O(n2)

#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

posted @   onlyblues  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2023-03-05 异或值
2022-03-05 聪明的燕姿
Web Analytics
点击右上角即可分享
微信分享提示