zoukankan      html  css  js  c++  java
  • 求出最多可以选择多少条不相交的线段

    问题一:

    给n条线段,求出最多有多少条线段互不相交。

    思路:

    这是一个经典问题。具体做法是贪心,也可以使用dp。

    贪心做法:按右端点排序,能选就选,不能就不选。因为如果不能选的话,它的加入一定会导致至少一条线段的退出,并且还使得当前线段集的最右端点右移了,一定不优。

    dp做法:f[i]表示坐标到i最多选多少条,枚举以i为起点的线段进行转移即可,可能需要进行离散化。

    问题二:

    给n条线段,线段可以平移,只需要满足右端点不超过一个值即可,当然左端点不能小于0,问最多有多少条线段互不相交。

    思路:

    这道题我们真的争论了很久,最后给出了一个nlog的贪心做法。而我自己想出来的是一个n^2时空的很臃肿的dp,但原题数据时1e4,所以应该也是合法的。

    先得到一些显而易见的推论:线段之间一定不能有空隙,因为如果有空隙一定可以将右面的向左移而不会更劣。如果按右端点递增为他们排序,那么最终的方案中线段编号一定是递增的,因为如果不是递增的,交换逆序的两条线段一定不会更劣。

    贪心做法:按右端点排序,对当前的已选择的线段集维护一个返回长度最大值的堆,依次枚举每一条线段,如果直接加到当前线段集的末尾可以,那么就加进去,如果不可以,比较它和堆顶线段的长度,留下一个长度比较短的,扫一遍答案就出来了。这用到了上面的两个结论。

    这是一种"可反悔的贪心",值得学习。

    dp做法:按右端点排序,f[i][j]表示到坐标i时,最后一条线段编号为j时最多选多少条,先考虑暴力n^3的方法,就是对于每个j枚举后面所有的线段进行转移,考虑优化,我们发现转移到f[j][k]的情况,事实上是f[i][1~k-1]转移的,所以我们只需要维护一个前缀的最大值就可以实现O1的转移。需要注意这种方法不能进行离散化,也就是如果坐标范围很大是无法使用的,因为我们没办法求出所有线段长度可以组合出的长度并将其离散化。

    这种通过记录前缀最大值的方式优化一维dp的方法应该是具有普遍意义的,需要掌握。

  • 相关阅读:
    JAVA对象之生
    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式
    [MySQL 5.6] 初识5.6的optimizer trace
    [MySQL5.6] 一个简单的optimizer_trace示例
    PERFORMANCE_SCHEMA 详解
    MetaData Lock 杨奇龙 ---MYSQL博客专家
    ArcEngine控制台应用程序
    一位数据科学家的私房工具清单
    数据可视化之热力图
    数据可视化之MarkPoint
  • 原文地址:https://www.cnblogs.com/hyghb/p/12405236.html
Copyright © 2011-2022 走看看