algorithm - 如何证明这个贪心算法的最优性?

标签 algorithm proof

给定 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++ 语言算法:

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);

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

最佳答案

重构后,我们尝试用尽可能少的基数 2*L + 1 间隔覆盖输入中出现的数字集。你可以想象,对于一个区间[C - L, C + L],其中的所有数字都调整为C

给定任何按排序顺序排列的区间列表,我们可以在 k 中归纳地证明,仅考虑前 k 区间,前 k > of greedy 至少涵盖了尽可能多的输入。基本情况 k = 0 很简单。归纳地,贪婪覆盖下一个未覆盖的输入元素,并尽可能多地覆盖;任意解决方案中覆盖其下一个未覆盖输入元素的区间必须不在贪婪之后,因此任意解决方案不再有覆盖。

关于algorithm - 如何证明这个贪心算法的最优性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32691512/

相关文章:

algorithm - 最小化两个数组的绝对差之和

performance - 回溯对比贪心算法最大独立集

c - 可变大小数组与 C 中的 calloc

java - 检测最后一次 foreach 循环迭代

unit-testing - 证明单元测试的正确性

algorithm - 二叉树的实现

c++ - 图的切集,Boost Graph Library

algorithm - 插入二进制堆 : Number of exchanges in worst case

graph - 二部连通图证明

algorithm - 证明 n^2 + 5 log(n) = O(n^2)