ACM算法之贪心算法
一般使用贪心算法要满足两个条件:
a.贪心选择性质 —— 可通过做局部最优(贪心)选择来达到全局最优解。(贪心选择性质:这是贪心算法与动态规划的区别)
b.最优子结构性质 —— 问题的最优解包含了子问题的最优解。
贪心算法的基本思想
找出整体当中每个小的局部的最优解,并且将所有的这些局部最优解合起来形成整体上的一个最优解。因此能够使用贪心算法的问题必须满足下面的两个性质:
1.整体的最优解可以通过局部的最优解来求出;
2.一个整体能够被分为多个局部,并且这些局部都能够求出最优解。使用贪心算法当中的两个典型问题是活动安排问题和背包问题。
贪心算法的基本步骤 :
1、从问题的某个初始解出发。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。
3、将所有部分解综合起来,得到问题的最终解。
1.如何证明每一步所做的贪心选择,最终可以使最后结果最优。
2.如何制定可行的贪心策略。
3.贪心算法就是只要满足当前利益最大化即可,所以有时候得出的结果不是最优解。
区别:
动态规划一般是以“自底向上的方式解决问题(如数塔问题)”,而贪心是以“自上向下的方式解决问题(如HDU2037(活动安排)“。
最优子结构性质:这个性质是贪心和动规的共同点。也就是一个问题的最优解要包含其子问题的最优解。
举个例子来说;
背包问题
题意:抗洪抢险中,官兵在一家商店发现有 N 件物品:第 i 件物品值 Vi 元,重 Wi 磅(1<= i <= n),此处 Vi 和 Wi 都是整数。他希望抢救下的东西价值越高越好,但他的背包最多只能装下 W 磅的东西(W为整数)。有两种抢救方式:
(1)0-1背包问题
如果每件物品或被带走或被留下,应该带走哪几样东西?
(2)部分背包问题
如果允许可带走某个物品的一部分,应该带走哪几样东西,每件东西的重量是多少?
对于抢救方式一(1),考虑重量至多为 W 磅的最值钱的一包东西,若从中去掉物品 j ,余下的必须是从其余的 n-1 件物品中可带走的、重量至多为 W-Wj 的最值钱的一件东西;如果再从中去掉物品 i ,余下的也必须是从其余 n-2 件可带走的、重量至多为 W-Wj-Wi 的最值钱的一件东西,以此类推
void fangshi_1(int x[],Type v[],Type w[],Type c,int n) { sort(n,v,w);//按物品价值排序 for(int i=1;i<=n;i++) x[i]=0; //x[i]=1 表示第 i 艰难物品装入背包,否则不装 for(int i=1;i<=n;i++){ if(w[i]<=c){ x[i]=1; c-=w[i]; } } }
如果考虑从最优货物中去掉某物品 j 的重量 Wp (Wj >= Wp),则余下的物品必须是可以从 N-1 件原有物品和物品 j 的 Wj-Wp 中可带走的、重量至多为 W-Wp 的最值钱的一件东西,以此类推
void fangshi_2(int n,float M,float v[],float w[],float x[]) { int i; sort(n,v,w); for(i=1;i<=n;i++) x[i]=0; //x[i] 表示装入的程度 float c=M; for(i=1;i<=n;i++){ if(w[i]>c) break; x[i]=1; c-=w[i]; } if(i<=n) x[i]=c/w; //注意剩余情况 }