算法之贪心法(java)可拆背包问题

算法之贪心法(java)可拆背包问题

1.概述

(1) 贪心算法(Greedy Algorithm)又称贪婪算法,是一种着眼局部的简单而适应范围有限的优化策略。
(2) 贪心算法在求解最优化问题时,从初始阶段开始,每一个阶段总是做一个使局部最优的贪心选择。

2.设计思想

贪心法是一种简单有效的方法。它在解决问题的策略上只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。
贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。这种局部最优选择并不总能获得整体最优解,但通常能获得近似最优解。如果一个问题的最优解只能用蛮力法穷举得到,则贪心法不失为寻找问题近似最优解的一个较好办法

3.实例理解 单源最短路径问题

如下的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下页的表中

算法之贪心法(java)可拆背包问题_第1张图片
算法的迭代过程:
算法之贪心法(java)可拆背包问题_第2张图片

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;

你可能感兴趣的:(java,贪心法,可拆背包问题)