用贪心算法解决0-1背包问题

1)、算法原理

    贪心算法总是作出在当前看来是最好的选择,即贪心算法并不从整体最优解上加以考虑,它所作出的选择只是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广的许多问题它能产生整体最优解。如图的单源最短路径、最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好近似解。

贪心算法求解的问题一般具有两个重要性质:贪心选择性质和最优子结构性质。所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

2)、解决0-1背包算法分析

这两类问题都具有最优子结构性质。对于0-1背包问题,设A是能装入容量为c的背包的具有最大价值的物品集合,则Aj=A-{j}n-1个物品1,2,…,j-1,j+1,…,n可装入容量为c-wj的背包的具有最大价值的物品集合。

用贪心算法求解0-1背包问题的步骤是,首先计算每种物品单位重量的价值vi/wi;然后,将物品进行排序,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总量未超过c,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直进行下去,直到背包装满为止。

(3)、算法实现

import javax.swing.*;

public class Knapsack extends JFrame{

 /**
  * @param args
  */
 

 public static int []flag;//保存原有的位置
  
 final JScrollPane scrollPane = new JScrollPane();
 public static JTextArea resulttextArea;
 public JLabel l1 = new JLabel(“最优解”);
 public JLabel l3 = new JLabel(“所用时间”);
 public static JTextField t1 = new JTextField();
 public static JTextField t2 = new JTextField();
 final JLabel label = new JLabel();
 final JLabel label_1 = new JLabel();
 
 
 public Knapsack(){
  this.setResizable(false);
  this.setTitle(“贪心算法计算0-1背包”);
  this.getContentPane().setLayout(null);
  this.setBounds(100, 100, 670, 400);
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  
  scrollPane.setBounds(190, 25, 454, 293);
  getContentPane().add(scrollPane);

  resulttextArea = new JTextArea();
  resulttextArea.setEditable(false);
  scrollPane.setViewportView(resulttextArea);
  
  
  label.setHorizontalTextPosition(SwingConstants.RIGHT);
  label.setHorizontalAlignment(SwingConstants.RIGHT);
  label.setText(“最优解:”);
  label.setBounds(10, 42, 66, 18);
  getContentPane().add(label);
  
  t1.setHorizontalAlignment(SwingConstants.RIGHT);
  t1.setHorizontalAlignment(SwingConstants.RIGHT);
  t1.setBounds(80, 42, 66, 18);
  getContentPane().add(t1);
  
  
  label_1.setHorizontalTextPosition(SwingConstants.RIGHT);
  label_1.setHorizontalAlignment(SwingConstants.RIGHT);
  label_1.setText(“所用时间:”);
  label_1.setBounds(10, 75, 66, 18);
  getContentPane().add(label_1);
  
  t2.setHorizontalAlignment(SwingConstants.RIGHT);
  // t1.setHorizontalTextPosition(SwingConstants.RIGHT);
  t2.setHorizontalAlignment(SwingConstants.RIGHT);
  t2.setBounds(80, 75, 66, 18);
  getContentPane().add(t2);
 }
 
  //最优装载函数(单位价值最高者先装)
 public  static void Loading(int v[],int w[],int c,int n){
  double []t = new double[n+1];
  int x[] = new int[n];//存放物品是否放入的序列
  int maxValue = 0;//最大价值
  flag = new int[n];
  //计算物品的单位价值
  for(int i = 0; i< n; i++){
   flag[i] = i;
   t[i] =(double) v[i]/w[i];
  }
  
  //对物品的价值进行排序,并且将价值和重量在数组中也进行重新排序
  double temp = 0;
  int temp1;
  int valuetemp = 0;
  int weighttemp = 0;
  int j;
  for(int i = 0;i<n;i++){
   for( j = n-1; j>i;j–){
    if(t[j] > t[j-1]){
        //交换单位价值
     temp = t[j];
     t[j] = t[j-1];
     t[j-1] = temp;
     //交换价值对应的位置
     valuetemp = v[j];
     v[j] = v[j-1];
     v[j-1] = valuetemp;
     //交换重量对应的位置
     weighttemp = w[j];
     w[j] = w[j-1];
     w[j-1] = weighttemp;
     
     temp1 = flag[j];
     flag[j] = flag[j-1];
     flag[j-1] = temp1;
    }
   }
  }
  //初始化装在序列
  for(int i = 0; i < n ; i++){
   x[i] = 0;
  }
  //将物品按单位价值放入背包中,并且确定小于等于背包的容量
  int i = 0;
  for(i =0; i <n && w[i] < c;i++){
   x[i] = 1;
   maxValue += v[i];
   c -= w[i];//容量减少
  }
  //如果背包还没放满
  int k = i;
  if(c!=0){
   for(k = i;k<n;k++){
    if(w[k]<=c){
     maxValue +=v[k];
     x[k] = 1;
     c -= w[k];
    }
   }
  }
  
  //看背包是全部放满还是有剩余
  System.out.print(“背包容量还剩下:”+c);
  System.out.println(“——————————————-“);
  System.out.println(“物品的选择(‘0’代表没有选择,‘1’代表选择)如下:”);
        System.out.println(“——————————————-“);
        resulttextArea.append(“物品的选择(‘0’代表没有选择,‘1’代表选择)如下:/n”);
  //输出最后的结果,放入背包中的物品的序列和最大的序列
  System.out.println(“最大价值为:”+maxValue);
  t1.setText(“”+maxValue);
  
  for(i = 0; i < n; i++){
   
   System.out.println(“重量是:”+w[i]+” 价值是:”+v[i]+” 是否装入背包中:”+x[i]);
   resulttextArea.append(“x[“+flag[i]+”]=”+x[i]+”/n”);
  }
  
 }
 
 @SuppressWarnings(“static-access”)
 public static void main(String[] args) {

  final int c=1000;
  final int n=50;
  
  int[] v={220,208,198,192,180,180,
   165,162,160,158,155,130,
   125,122,120,118,115,110,
   105,101,100,100,98,96,
   95,90,88,82,80,77,
   75,73,70,69,66,65,
   63,60,58,56,50,30,
   20,15,10,8,5,3,
   1,1};
  int[] w={80,82,85,70,72,70,
   66,50,55,25,50,55,
   40,48,50,32,22,60,
   30,32,40,38,35,32,
   25,28,30,22,50,30,
   45,30,60,50,20,65,
   20,25,30,10,20,25,
   15,10,10,10,4,4,
   1,1};
  long start = System.currentTimeMillis();
  Knapsack sack = new Knapsack();
  sack.Loading(v,w,c,n);
  sack.setVisible(true);
  
  double end = System.currentTimeMillis();
  t2.setText((end – start)+”ms”);
 }

}

 

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/shuangdui/article/details/6005938
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞