算法之贪心法(java)可拆背包问题
1.概述
(1) 贪心算法(Greedy Algorithm)又称贪婪算法,是一种着眼局部的简单而适应范围有限的优化策略。
(2) 贪心算法在求解最优化问题时,从初始阶段开始,每一个阶段总是做一个使局部最优的贪心选择。
2.设计思想
贪心法是一种简单有效的方法。它在解决问题的策略上只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。
贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。这种局部最优选择并不总能获得整体最优解,但通常能获得近似最优解。如果一个问题的最优解只能用蛮力法穷举得到,则贪心法不失为寻找问题近似最优解的一个较好办法
3.实例理解 单源最短路径问题
如下的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下页的表中

算法的迭代过程:

4.贪心策略(原则)的选择
- 贪心算法没有固定的算法框架,算法设计的关键在于贪心策略的选择与确定。
- 贪心算法的基本思想是通过一系列选择步骤来构造问题的解,每一步都是对当前部分解的一个扩展,直至获得问题的完整解。
- 应用贪心算法所做的每一步选择都必须满足:
(1)可行的:必须满足问题的约束条件。
(2)局部最优:当前所有可能的选择中选择使局部最优的决策。
(3)不可取消:选择一旦做出,在后面的步骤中无法改变。
5.贪心算法的设计步骤
贪心算法的设计步骤可概括为三步:
1、确定贪心策略
根据问题的特点,确定贪心策略,即究竟怎样进行选择才最有可能得到最优解,但贪心策略不好确定,没有现成的方法或理论,需要我们通过已有的知识和经验通过猜测来得到。
2、证明贪心策略的正确性
贪心策略往往是通过猜测得到的,那么据此是否对于问题的所有实例都能得到最优解,需要进行证明。贪心策略的正确性证明是一个难点,通常使用数学归纳法来证明。
3、根据贪心策略设计贪心算法
证明贪心策略的正确性后,根据这个贪心策略来设计贪心算法,从而求得问题的最优解。
6.可拆背包问题
给定n个物品和一个背包,物品i的重量为wi且wi>0,若将物品i全部装进背包,将获得一个价值pi且pi>0,背包问题是说如何来选择将物品装进背包,使背包中的物品的价值达到最大。
有两种不同的背包问题:
物品不可分割,只能作为整体或者装进背包,或者不是,这种背包问题称为0-1背包问题。无法用贪心法得到最优解,只能得到近似解。
物品可以分割,也就是说允许将物品的一部分装进背包,这种背包问题为一般背包问题,本节讨论如何用贪心法求解一般背包问题。
问题分析:
设用xi来表示物品i装入背包的情况,有0≤xi≤1。则物品i装进背包那部分重量为wixi,物品i装进背包所获得的价值为pixi。则一般背包问题就是要求一个n元向量或一个n元组:
X={x1,x2,…,xn} xi(1≤i≤n)∈[0,1]
使得这n个物品按照X的方式装进背包不超过背包的载重量M,且获得最大价值,即有背包问题满足约束条件:

且使目标函数达到最大,即

例:
设有3个物品,重量分别为(w1,w2,w3)=(18,15,10),各个物品价值为(p1,p2,p3)=(25,24,15),背包载重量为W=20。
贪心策略1:按照 pi 从大到小装包
(1, 2/15, 0) 目标函数28.2
贪心策略2:按照 wi 从小到大装包
(0, 2/3, 1) 目标函数31
贪心策略3:按照 pi/wi 从大到小装包
(0, 1,1/2) 目标函数31.5
// 对n件物品按单位重量的价值降序排序
typedef struct{ float p,w,v; }object;
object a[100],t;
float x[100];
for(i=1;i<=n;i++){
a[i].v=a[i].p/a[i].w;
x[i]=0;
}
for(j=1;j<n;j++)
for(i=1;i<=n-j;i++)
if(a[i].v<a[i+1].v)
{ t=a[i]; a[i]=a[i+1]; a[i+1]=t;
// 已对n件物品按单位重量的效益降序排序
cw=w;p=0; // cw为背包还可装的重量
for(i=1;i<=n;i++)
{if(a[i].w>cw) break;
x[i]=1.0; // 若a[i].w<=cw,整体装入
cw=cw−a[i].w;
p=p+a[i].p;
}
x[i]=(float)(cw/a[i].w); // 若a[i].w>cw,装入一部分)
p=p+x[i]*a[i].p;
本文深入探讨了贪心算法的设计思想和应用,通过实例解析单源最短路径问题,阐述了贪心策略的选择原则,并详细讲解了可拆背包问题的解决方法。
可拆背包问题&spm=1001.2101.3001.5002&articleId=102490033&d=1&t=3&u=4dff50135e274f9e9d6913e8b545399a)
1605

被折叠的 条评论
为什么被折叠?



