点覆盖问题

时间:2010-05-12 18:19:27

标签: algorithm greedy

我最近在测试中遇到了这个问题:给定一组点 m (全部在x轴上)和一组 n 的带有端点的线[< em> l,r ](再次在x轴上),找到 n 的最小子集,使得所有点都被一条线覆盖。证明您的解决方案始终找到最小子集。

我为它写的算法是有效的: (比如将行存储为数组,左端点位于0位,右端位于位置1)

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

我只是不确定这总是找到最小的解决方案。这是一个简单的贪婪算法,所以我的直觉告诉我它不会,但我的一个比我好得多的朋友说,对于这个问题,像这样的贪婪算法总能找到最小的解决方案。为了证明我的总是找到最小的解决方案我做了一个非常手的波浪证明矛盾,我做了一个假设,可能根本不是真的。我完全忘记了我的所作所为。

如果这不是一个最小的解决方案,有没有办法在比O(n!)时间更短的时间内完成它?

由于

2 个答案:

答案 0 :(得分:7)

您的贪婪算法 IS 正确无误。 我们可以通过显示任何其他覆盖只能通过用您的算法生成的封面替换它来改进来证明这一点。

设C是给定输入的有效覆盖(不一定是最优的),并根据您的算法使S成为覆盖。现在让我们检查点p1,p2,... pk,它们代表你在每个迭代步骤中处理的最小点。覆盖物C也必须覆盖它们。观察到C中没有任何部分覆盖其中两个点;否则,你的算法会选择这个细分!因此,| C |&gt; = k。算法中的成本(段数)是多少? | S | = K。

完成证明。

两个注释:

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

2)实际上这个问题是Set Cover问题的简化版本。虽然原始是NP完全的,但这种变化导致多项式。

答案 1 :(得分:0)

提示:首先尝试证明你的算法适用于大小为0,1,2的集合......并看看你是否可以推广它以通过归纳创建证据。