用贪心算法求解背包问题

 1   背包问题的描述:

    已知有n种物品和一个可容纳M重量的背包,每种物品i的重量为 。假定将物品i的一部分 放入背包就会得到 的效益,这里, , 。显然,由于背包容量是M,因此,要求所有选中要装入背包的物品总重量不得超过M.。如果这n件物品的总重量不超过M,则把所有物品装入背包自然获得最大效益。现需解决的问题是,这些物品重量的和大于M,该如何装包。

2 用贪心策略求解背包问题

   首先需选出最优的量度标准。不妨先取目标函数作为量度标准,即每装入一件物品就使背包获得最大可能的效益值增量。在这种量度标准下的贪心方法就是按效益值的非增次序将物品一件件放到背包中去。如果正在考虑中的物品放不进去,则可只取其一部分来装满背包。但这最后一次的方法可能不符合使背包每次获得最大效益增量的量度标准,这可以换一种能获得最大增量的物品,将它(或它的一部分)放入背包,从而使最后一次装包也符合量度标准的要求。算法如下所示。

算法1   背包问题的贪心算法

procedure  GREEDY-KNAPSACK(P,W,M,X,n)

 //P(1:n)和W(1:n)分别含有按P(i)/W(i)≥P(i+1)/ W (i+1)排序的n件物品的效益值和重量。M是背包的容量大笑,而X(1:n)是解向量。//

                  real P(1:n),W(1:n),X(1:n),M,cu;

     integer  i,n;

X 0   //将解向量初始化为零

cu M  //cu是背包剩余容量

for  i 1 to n do

    if  W(i)>cu  then  exit  endif

   X(i) 1

   cu cu-W(i)

repeat

if  i≤n  then  X(i) cu/W(i)

endif

end  GREEDY-KNAPSACK

 

3 具体问题

求以下情况背包问题的最优解:n=7,M=15,( )=(10,5,15,7,6,18,3)和( )=(2,3,5,7,1,4,1)。

程序清单:

/**GreedyKnapsack.java

 * 求所给背包问题的最优解

 */

package com.algorithm.knapsack;

import java.util.*;

public class GreedyKnapsack {

 public void Knapsack(double P[],double W[],int M,int n)

 { 

 int i ;

 double X[] = new double[n]; //定义结果向量

 for(i=0;i<X.length;i++)

 X[i] = 0;

 double cu = M; //cu是背包剩余重量

 for(i=0;i<n;i++)

 { if(W[i]>cu)

 break;

     X[i] = 1;

     cu = cu-W[i];

 }

// System.out.println(i);

 if(i<n)

 X[i] = cu/W[i];

 System.out.println("问题的解为");

 for(int k=0;k<X.length;k++)

 System.out.print(X[k] + " ");

 }

 

public static void main(String[] args){

 double P[] = {10,5,15,7,6,18,3}; //效益数组

 double W[] = {2,3,5,7,1,4,1};

 int M = 15,n = 7;

 double PW[] = new double[P.length];

 int[] index = new int[n];

 for(int i= 0;i<n;i++){

 PW[i] = P[i] / W[i];

 index[i] =i;

 }

 double temp =0;

     for(int i=0;i<n-1;i++)

     {

       for(int j=i+1;j<n;j++)

      {

     if(PW[i]<PW[j])       //对效益/重量数组按递增进行排序

     {

     temp = PW[i];  

     PW[i] = PW[j];

     PW[j] = temp;

     int x=index[i];       //交换相应的数组下标

     index[i] = index[j];

      index[j] = x;               

     }

       }

     }

double[] w1 = new double[n];

double[] p1 = new double[n];

for(int i=0;i<n;i++)      

{

w1[i]=W[index[i]];     //将排序后的重量和价值数组分别赋给w1[]p1[]

p1[i]=P[index[i]];

}

 System.out.println("各物品效益/重量的值为:");

 for(int i=0;i<n;i++)

 System.out.print(PW[i]+" ");

 System.out.println();

 System.out.println ("相应的重量数组为:"+Arrays.toString(w1));  

 System.out.println ("相应的效益数组为:"+Arrays.toString(p1));

 GreedyKnapsack gk = new GreedyKnapsack();

 gk.Knapsack(P,W,M,n);

 }

}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是你的春哥!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值