改进的附近学校/邮局示例的贪婪算法方法

时间:2016-02-25 21:27:19

标签: algorithm greedy

我一直试图从教授的笔记中解决练习题,但找不到最佳解决方案。以下是问题所在。

沿着西南街道,有m所公立学校分别有距离,S [1]< S [2]< ......< S [m],到街道的西端。除了m所学校之外,还有n个房屋的距离为H [1]< H [2]< ......< H [n]分别位于街道的西端。目前,任何一所学校的学生都可以找到距离步行200米的学校。现在,由于预算很短,我们希望关闭一些学校。请设计一个O(n + m)贪婪算法,以选择最少数量的学校开放,这样任何家庭仍然可以找到200米步行距离内选定的学校之一。您需要显示伪代码并证明算法的正确性。

2 个答案:

答案 0 :(得分:1)

高层次的想法

首先,我们知道解决方案始终存在,而不是删除任何学校。

为了选择最低学校,让我们以另一种方式思考:

  

对于h [i]的每个房子,请考虑范围[h[i]-200, h[i]+200]包含

因此,对于每个这样的范围,我们希望在s[j]找到一些学校h[i]-200 <= s[j] <= h[i]+200

同时h[]&amp; s[]已排序,让我们从最左边的房子[h[0]-200, h[0]+200]看到,我们必须为这所房子选择一所学校,直观地说,我们要选择最右边的学校可能,因为这所学校更高的机会 与下一个房子分享

这个想法在一般情况下是正确的:

  

对于范围h [i],我们总是希望选择h [i-?]或最右边的非选择学校已选择学校的学校

<强>正确性

让解决方案是一组有序的学校S,这是由所描述的方法找不到的

让我们贪婪的方法找到的解决方案是一组有序的学校G

考虑S[0]G[0]S[0] <= G[0],因为我们为第一所房子选择了最合适的学校。

  1. S[0] <= G[0] <= S[1],我们可以将S[0]替换为提供相同设置尺寸的G[0]
  2. S[0] < S[1] < ... < S[X] <= G[0] <= S[X+1],我们可以将所有S[X]&lt; = G[0]替换为G[0],这会提供更小/更优的尺寸
  3. (确实是案例1是案例2的子案例)

    对于这两种情况,删除G[0]和任何S[X] <= G[0],场景与两个简化集相同,我们可以递归地使用类似的参数来表示我们的贪婪方法不会比任何可能的解决方案更糟糕,这是最佳的

    伪代码

    &#13;
    &#13;
    Pointer house_pointer = first house, school_pointer = first school;
    
    for( each house ){
       if( NOT ( current school is chosen and within current house's range ) ){
           while(current school is NOT the rightmost school within range){
                school_pointer = current school = next school
           }
           mark current school chosen
       }
       house_pointer = next house
    }
    &#13;
    &#13;
    &#13;

    似乎算法中有两个循环,即O(nm),但事实并非如此。对于使用两个指针迭代数组的这些类型的结构(例如KMP algorithm),通常可以观察每个元素将被访问的最大次。

    对于房屋,每次迭代都会搬到下一个房子,每个房子最多只能进入一次。

    对于学校来说,由于指针只向前移动而不是向后移动,每个学校最多只能访问一次,但每个房子迭代的分配不均匀(取决于实施,有些学校可能会被访问​​2次但是#&# 39;不重要)

    因此,结合两者,复杂性仍为O(n+m)

答案 1 :(得分:0)

从问题的初始状态我们知道| S [1] - H [j] | &lt; = 200,对于某些j,所以我们可以从那里开始。

如果| S [2] - H [j] |,我们选择放弃第一所学校&lt; = 200,如果| S [3] - H [j] |,我们将放弃第二所学校&lt; = 200 ......等等。这个想法是贪婪并最大化学校的覆盖范围,使其与下一个需要覆盖的房屋保持最大距离。

一般来说,对于S [i]的学校和H [j]的一所学校,如果| S [i + 1] - H [j] |,我们将放弃学校。 &lt; = 200.如果| S [i + 1] - H [j] | &GT; 200然后我们把学校留在S [i]并找到不在S [i]距离内的下一所房子。所有房屋都被覆盖后,算法就完成了。运行时间为O(n + m),因为在最坏的情况下,我们迭代S和H一次。

为了证明正确性,你应该尝试考虑一个最佳的顺序,并证明你的贪婪解决方案不会做得更糟。例如。给定学校的最佳解决方案O [1]&lt; O [2]&lt; ......&lt; O [K]和你贪婪的G [1]&lt; 1&lt; G [2]&lt; ......&lt; G [L],证明L <= K。