牛客练习赛122

D:圆

正着求删除的最小代价不好做,采用逆向思维,求选择一些不相交的线段使得构成一个圆的代价尽量大,最后答案就是所有线段权值之和减去最大代价。

那么如何求这个最大代价呢?显然区间DP

老套路:破环成链,枚举区间长度 len ,枚举区间左端点 i 和右端点 j

很明显没有线段长度为1,故len从2开始

具体的

线段的操作和点的相似但又不完全相同具体看代码即可。

1:不选择以左端点的线段,

2、选择以为左端点的线段。枚举左端点 所能到达的右端点 v,权值为 w,那么当前的答案

由 区间 的答案加上 区间 的答案加上线段 的权值构成,即

复制代码
int n, m;
int f[M][M]; // f[i][j]  区间i到j不相交边的最大价值
vector<PII> g[N];
void solve()
{
    cin >> n >> m;
    int s = 0;
    for (int i = 1; i <= m; i++)
    {
        int x, y, w;
        cin >> x >> y >> w;
        if (x > y)
            swap(x, y);
        g[x].pb({y, w});
        g[y].pb({x + n, w});
        s += w;
    }
    for (int len = 2; len <= 2 * n; len++)
    {
        for (int i = 1; i + len - 1 <= 2 * n; i++)
        {
            int j = i + len - 1;
            f[i][j] = f[i + 1][j]; // 不选择以i为左端点的线段
            for (auto ed : g[i])   // 选择以i为左端点的线段
            {
                int v = ed.xx, w = ed.yy;
                if (v > j) // 已经越过右端点了
                    continue;
                if (v - 1 > i + 1) //区间端点,不能相同
                    w += f[i + 1][v - 1];
                if (j > v + 1)
                    w += f[v + 1][j];
                f[i][j] = max(f[i][j], w);
            }
        }
    }
    int tmp = 0;
    for (int i = 1; i <= n; i++)
        tmp = max(tmp, f[i][i + n - 1]);
    s = s - tmp;
    cout << s << endl;
}

类似的题目

Codeforces Round 661 (Div. 3)

F. Yet Another Segments Subset

两个题目非常相似但是又不完全相同。

本题的数据显然如果直接区间dp会超时,但是n却是很小我们想能不能进行离散化。

本题的相交比较上一题有点不同,不同在包含的时候端点可以相交,而不包含时端点不可相交。

很明显,离散化候不同区间值被拉近了距离,但是不相交得还是不相交,所以本题可以离散化。(具体题目具体分析,有的题目可能会有坑)

状态表示: 表示区间 里面满足题意得最大区间数量。

然后我们就想一下转移方程:

具体的还是区间DP的过程,枚举区间长度 len ,枚举区间左端点 i 和右端点 j

我们还是以选不选以 为左端点的区间,

1:不选

2:选

我们看第二个方程,很明显就是我们上面说的;

即只有完全包含端点才可以相同;

我们还要注意一种情况那就是区间恰好等于 ,这种情况由于 ,被跳过了

所以最后加上个数即可完成。

复制代码
int n;
PII p[N];
vector<int> g[N];
void solve()
{
    vector<int> t;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int l, r;
        cin >> l >> r;
        p[i] = {l, r};
        t.pb(l);
        t.pb(r);
    }
    sort(t.begin(), t.end());
    t.erase(unique(t.begin(), t.end()), t.end());
    for (int i = 1; i <= n; i++)
    {
        int x = lower_bound(t.begin(), t.end(), p[i].xx) - t.begin() + 1;
        int y = lower_bound(t.begin(), t.end(), p[i].yy) - t.begin() + 1;
        g[x].pb(y);
    }
    int m = t.size();
    vector<vector<int>> f(m + 10, vector<int>(m + 10));
    for (int len = 1; len <= m; len++)
    {
        for (int i = 1; i + len - 1 <= m; i++)
        {
            int j = i + len - 1;
            f[i][j] = f[i + 1][j];
            int cnt = 0;
            for (auto ed : g[i])
            {
                int v = ed;
                if (v == j)
                    cnt++;
                if (v < j)
                    f[i][j] = max(f[i][v] + f[v + 1][j], f[i][j]);
            }
            f[i][j] += cnt;
        }
    }
    cout << f[1][m] << endl;
    for (int i = 0; i <= m + 1; i++)
        g[i].clear();
}
相关推荐
格林威14 分钟前
常规线扫描镜头有哪些类型?能做什么?
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测·工业镜头
程序员莫小特2 小时前
老题新解|大整数加法
数据结构·c++·算法
过往入尘土3 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.3 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
蒙奇D索大3 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
智驱力人工智能4 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
程序员爱钓鱼5 小时前
Go语言实战案例——进阶与部署篇:编写Makefile自动构建Go项目
后端·算法·go
_Power_Y5 小时前
Java面试常用算法api速刷
java·算法·面试
艾醒(AiXing-w)5 小时前
大模型面试题剖析:模型微调中冷启动与热启动的概念、阶段与实例解析
人工智能·深度学习·算法·语言模型·自然语言处理
天选之女wow6 小时前
【代码随想录算法训练营——Day32】动态规划——509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯
算法·leetcode·动态规划