Algorithm 点覆盖问题

Algorithm 点覆盖问题,algorithm,greedy,Algorithm,Greedy,我最近在一次测试中遇到了这个问题:给定一组点m(都在x轴上)和一组n条端点为[l,r](同样在x轴上)的线,找到n的最小子集,使所有点都被一条线覆盖。证明您的解决方案总是找到最小子集 我为它编写的算法是这样的: (假设线存储为数组,左端点位于位置0,右端点位于位置1) 算法覆盖点(集合[]m,集合[]n): chosenLines=[] 虽然m不是空的: 最小值=最小值(m) bestLine=n[0] 对于长度为n的i=1: 如果n[i][0]最佳行[1],则 bestLine=n[i] 将b

我最近在一次测试中遇到了这个问题:给定一组点m(都在x轴上)和一组n条端点为[l,r](同样在x轴上)的线,找到n的最小子集,使所有点都被一条线覆盖。证明您的解决方案总是找到最小子集

我为它编写的算法是这样的: (假设线存储为数组,左端点位于位置0,右端点位于位置1)

算法覆盖点(集合[]m,集合[]n):
chosenLines=[]
虽然m不是空的:
最小值=最小值(m)
bestLine=n[0]
对于长度为n的i=1:
如果n[i][0]最佳行[1],则
bestLine=n[i]
将bestLine添加到chosenLines
对于i=0到m的长度:

如果m[i]提示:首先尝试证明您的算法适用于大小为0、1、2的集合。。。然后看看你是否可以将其推广,通过归纳法来创建一个证明。

你的贪婪算法是正确的。 我们可以证明这一点,证明任何其他覆盖只能通过用您的算法生成的覆盖替换它来改进

设C为给定输入的有效覆盖(不一定是最优覆盖),并根据您的算法设为覆盖。现在让我们检查点p1、p2。。。pk,表示在每个迭代步骤中处理的最小点。覆盖层C也必须覆盖它们。观察C中没有覆盖其中两点的线段;否则,您的算法将选择此段!因此,| C |>=k。您的算法的成本(分段数)是多少|S |=k

这就完成了证明

两个注释:

1) 实现:使用n[0]初始化bestLine是不正确的,因为循环可能无法改进它,并且n[0]不一定涵盖minX


2) 实际上,这个问题是这个问题的简化版本。虽然原始代码是NP完全的,但此变体的结果是多项式。

我在跟踪您的伪代码时遇到了问题。什么是<代码> n[i] [0 ]抱歉,我的意思是考虑点<代码> 1, 100, 101,102, 103, 104 和行<代码> [1, 100 ] [10, 101 ] [20, 102 ] [30, 103 ] [40, 104 ] [101, 104 ] < /代码>。如果我正确理解了您的算法,它将选择
[1100]
覆盖前两点,
[10101]
覆盖第三点,直到
[40104]
覆盖最后一点。我们可以通过选择
[1100]
[101104]
[1100]
[40104]
做得更好。如果我正确理解了你的算法,那么它不会适用于所有情况。@IVlad:不,按照我对算法的理解,它会选择覆盖当前点且具有最大右点的线段。事实上,它将返回[1100],[101104]。然而,我认为这个算法有一点缺陷。将bestLine初始化为n[0]可能不是正确的做法。听起来不错,谢谢您的帮助。我确实忘记了用给定的线覆盖点是不可能的,你是对的。
algorithm coverPoints(set[] m, set[][] n):
    chosenLines = []
    while m is not empty:
        minX = min(m)
        bestLine = n[0]
        for i=1 to length of n:
            if n[i][0] <= minX and n[i][1] > bestLine[1] then
                bestLine = n[i]
        add bestLine to chosenLines
        for i=0 to length of m:
            if m[i] <= bestLine[1] then delete m[i] from m
    return chosenLines