代码之家  ›  专栏  ›  技术社区  ›  Peach

如何证明这种贪婪算法的最优性?

  •  1
  • Peach  · 技术社区  · 9 年前

    给定N个整数。这些数字中的每一个都可以增加或减少一次,但不能超过给定的正整数L。在每次运算之后,如果任何数字变得相等,我们将它们视为一个数字。问题是计算不同整数的最小集合的基数。

    约束:N<=100,L<=3200,整数在[-32000,32000]范围内

    示例:N=3,L=10 11 21 27

    1) 将11增加10=>21 21 27
    2) 减少27 6=>21 21 21

    答案是1。

    C++语言中的Algo:

    sort(v.begin(), v.end());
    // the algo tries to include elements in interval of length 2 * L
    int ans = 0;
    int first = 0; 
    for(int i = 1; i < N; ++i) {
        if(v[i] - v[first] > 2 * L) { // if we can't include i-th element 
            ans++;                    // into the current interval   
            first = i;                // the algo construct new 
        }
    }
    ans++;
    printf("%d", ans);
    

    我试图理解为什么这种贪婪的算法是最优的。感谢任何帮助。

    1 回复  |  直到 9 年前
        1
  •  2
  •   David Eisenstat    9 年前

    我们试图以尽可能少的基数间隔覆盖输入中出现的一组数字 2*L + 1 尽可能地。你可以想象,在一段时间内 [C - L, C + L] ,其中的所有数字都调整为 C .

    给定任何按排序顺序排列的间隔列表,我们可以在 k 考虑到第一个 k 间隔,第一个 k 贪婪至少覆盖了同样多的输入。基本情况 k = 0 是微不足道的。感应地,贪婪覆盖下一个未覆盖的输入元素,并尽可能多地覆盖;任意解中覆盖其下一个未覆盖的输入元素的间隔必须不在贪心之后,因此任意解没有更多的覆盖。