算法设计与分析论文(贪心算法)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.1 贪心选择
贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪 心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划 算法的主要区别。
贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择 就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否 具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最 优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作 了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法 证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。
物品超出背包容量为止。伪代码如下:
public static void DepWePr(double[][] a, double c, int[] ans) { // depend on
// the // weight // and price double[] w = new double[a[0].length]; // the weight of goods System.arraycopy(a[0], 0, w, 0, w.length); // copy the array
贪心算法
——不在贪心中爆发,就在贪心中灭亡 徐晓龙 武汉理工大学计算机科学与技术学院软件 ZY1101 班
摘要
本文介绍贪心算法的基本意义以及算法的使用范围,并通过具体的案例来分 析贪心算法的具体应用,从而指出其特点和存在问题。 关键字:贪心算法,贪心策略,TSP、0/1 背包
引言
我们用了 13 周的时间学完了《算法设计与分析》这本书。这本书中涵盖了 大量的常见算法,包括蛮力法、分治法、动态规划法、贪心算法等等。我最有印 象的就是贪心算法。贪心算法是一种有合理的数据组织和清晰高效的算法,它简 单有效。下面我们来详细解读一下这个算法。
1) 不能保证求得的最后解是最佳的。由于贪心策略总是采用从局部看来是 最优的选择,因此并不从整体上加以考虑。
}
程序运行结果见附录。 根据程序运行的结果,我们分别得到三个答案。放置的物品方案分别为: 10 20 、30 20 、10 30 。如此看来,根据价格的贪心策略是最“贪心” 的。其实不然,根据价格与重量比值的贪心策略的适应范围更加广阔,效果一般 来说也更加的好。本例中受到小数据的局限性,无法发挥出其真正的效果。 贪心策略之所以能成为贪心算法的核心,就是因为它决定着贪心算法是爆发 还是灭亡,以及爆发的程度。上面的例子用三种不同的贪心策略,结果也截然不 同。当扩大问题规模时,这种差距就更加的明显。
public void find(int[][] distance,int[] ans) { int j=1; //starting city for(int i=0;i<distance.length;i++) { ans[i]=j; j=min(distance[j-1],ans); } }
private int min(int[] a,int[] b) { int minN=0; int temp=100; EnumerationSearch sea = new EnumerationSearch(); for(int i=0;i<a.length;i++) { if(sea.search(b, (i+1))==-1) if(a[i]<temp) { temp=a[i]; minN=i; } } minN++; return minN;
double[] p = new double[a[0].length]; // the price of goods System.arraycopy(a[1], 0, p, 0, p.length); // copy the array double[] pw = new double[w.length]; for (int i = 0; i < w.length; i++)
depend // on // the // weight to select // goods { double[] w = new double[a[0].length]; System.arraycopy(a[0], 0, w, 0, w.length); EnumerationSearch sea = new EnumerationSearch(); Quick.Sort(w); for (int i = 0; w[i] <= c && i < w.length; i++) { c = c - w[i];
int j = sea.search(a[0], w[i]); ans[j] = 1; }
}
程序的运行结果见附录。
根据价格的贪心策略,即优先放置价格比较高的物品,以此来达到背包价格
更高的目的。首先需要将物品按照价格从大到小重新排序,然后依次放置物品,
直至下个物品超出背包容量为止。伪代码如下:
public static void DepPrice(double[][] a, double c, int[] ans) // depend on
贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某 个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的
选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行 解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加 算法停止。
3. 贪心算法的基本要素
// the price // to select goods {
double[] p = new double[a[1].length]; System.arraycopy(a[1], 0, p, 0, p.length); EnumerationSearch sea = new EnumerationSearch(); Quick.Sort(p); int i = (p.length - 1); int j = sea.search(a[1], p[i]); while (a[0][j] <= c && i >= 0) {
上求一个 Hamilton 圈Ch 使得
W(Ck ) w(e) min{各个Hamilton圈的权}。 eC k
贪心算法每选入一边都保证了是当前可选边中权值最小的边,这便是“贪心”
的含义。基本思想为首先选择图中任意顶点 u,并将 u 置于顶点集合的子集 S 中。 如果 S 是顶点集合 V 的真子集,就继续选择顶点 j 添加到子集 S 中, c[i][j]是权 值最小的边。按照同样的步骤不断进行贪心选择,直到子集 S=V 为止。此时,选 取到的所有的边就构成了一棵最小生成树。伪代码如下:
4. 贪心算法的核心
贪心算法的核心问题是选择能产生问题最优解的最优度量标准,即具体的贪 心策略。贪心策略决定着贪心算法是爆发或者是灭亡。所以,选择一个合理、正
确的贪心策略是至关重要的。下面用例子说明: 第一个例子我们选用大家熟知的 0/1 背包问题。给定 n 种物品和一个背包。
物品i 的重量是w i ,其价值为vi ,背包的容量为C 。在选择物品i 装入背包时, 不可以选择物品i 的一部分,一定要全部装入背包,1 i n 。应如何选择 装入背包的物品,使得装入背包中物品的总价值最大?
// price/weight pw[i] = p[i] / w[i]; double[][] wpw = new double[2][w.length]; // record the table of
// weight and pw System.arraycopy(w, 0, wpw[0], 0, w.length); System.arraycopy(pw, 0, wpw[1], 0, w.length); EnumerationSearch sea = new EnumerationSearch(); Quick.Sort(pw);
设 xi 表示物品i 装入背包的情况,根据问题的要求,有如下约束条件和目标 函数:
n
w ivi
C
i 1
0 xi 1
(1 i n)
n
max vixi i 1
于是,背包问题归结为寻找一个满足约束条件式,并使目标函数式达到最大的解
向量 X (x1,x2,…,xn ) 。 现在有一个容量为 50 的背包,共有三个物品,重量为别为 20、30、10,价
}
程序运行结果见附录。
同时我们运用动态规划法来求解同样的问题,问题规模为 8 个城市。动态求 解过程需要使用 10ms 的时间,而贪心算法只需要使用 1ms 以内的时间即可完成
计算,我们可以理解到贪心算法的爆发力了。但是,它们的结果并不相同。动态 规划法求解的答案为: 1->3->5->8->4->6->7->2->1,而贪心算法的答案为: 1->3->4->2->5->6->7->8->1。动态规划法需要走的路程为 21,而贪心算法需要 走的路程为 25。这就是贪心算法的特点,虽快但不一定准。贪心算法每次都是 局部寻优,很容易会陷入局部最优解的波谷。所以,贪心算法总结起来一共有三 个小缺点。
int i = (pw.length - 1); int j = sea.search(wpw[1], pw[i]); while (wpw[0][j] <= c && i >= 0) {
c = c - wpw[0][j]; ans[j] = 1; i--; j = sea.search(wpw[1], pw[i]); }
值分别为 60、120、50。现使用贪心算法来放置物品,贪心策略也对应有三种,
分别是根据重量、价格、重量与价格比。
根据重量的贪心策略,即优先放置重量小的物品,以此来达到放置更多个物
品的目的。首先需要将物品按照重量从小到大重新排序,然后从小到大的放置物
品,直至下个物品无法放进背包为止。伪代码如下:
public class worseGreedy { public static void DepWeight(double[][] a, double c, int[] ans) //
1. 贪心算法的含义
贪心算法可以简单描述为:对一组数据进行排序,找出最小值,进行处理,再 找出最小值,再处理。也就是说贪心算法是一种在每一步选择中都采取在当前状 态下最好或最优的选择,从而希望得到结果是最好或最优的算法。
2. 贪心算法的基本思想
贪心算法,法如其名,每次都贪心的选取当前最优解,一旦确定了当前解, 不管将来有什么结果,之后都不会再修正,这一点与动态规划法比起来稍有逊色。 如果一个问题的最优解只能用蛮力法穷举得到,则贪心法不失为寻找问题近似最 优解的一个较好办法。
5. 贪心法的特点
货郎担问题(或称旅行商问题或巡回售货员问题),是 NP 问题中的著名问题。 它通常的提法是:货郎到各村去卖货,再回到出发点处,每村到且仅到一次。为 其设计一种路线,使得所用旅行售货的时间最短。
建立数学模型时,把村庄设为结点,村庄与村庄之间的路线设为结点之间的
带权的边,则货郎担问题转化为在图上寻求最优 Hamilton 圈问题。即在加权图
c = c - a[0][j]; ans[j] = 1; i--; j = sea.search(a[1], p[i]); } }
程序的运行结果见附录。
根据重量与价格比值的贪心策略,即优先放置“性价比”高的物品,以此来
达到背包价格最大的目的。首先需要求出各个物品的价格与重量的比值,然后按
照这个参数来重新排序物品,价重比高的放前面。最后一次放入物品,直至下个
3.2 最优子结构
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性 质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该 问题可用贪心算法或动态规划算法求解的关键特征。贪心算法的每一次操作都对 结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做 出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退 功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题。
相关文档
最新文档