0-1背包问题

来源:互联网 发布:js slice和substring 编辑:程序博客网 时间:2024/06/07 22:10

一、动态规划法

package com.thirdwork;
/**
 * 0-1背包问题
 * @author YR
 */
public class Test1 {
    private static int[] weights = {0,50,30,45,25,5};//50,30,45,25,5
    private static int[] values = {0,200,180,225,200,50};//200,180,225,200,50
    private static int n = 5; //5
    private static int p = 100; //100
    
    public static void main(String[] args) {
int[][] sum = knapsackNp(values, weights, n, p);
System.out.print("重量为:");
for(int i = 1;i<=n;i++){
   System.out.print(weights[i]+"\t");
}
System.out.print("\n价值为:");
for(int i = 1;i<=n;i++){
   System.out.print(values[i]+"\t");
}
System.out.println("\n0-1背包求解最大价值为:"+sum[n][p]);

/*for(int i =0;i<=n;i++){
   for(int j =0;j<=p;j++)
System.out.print(sum[i][j]+"\t");
   System.out.println();
}*/
System.out.print("背包序号为:");
int[] x = track(sum, weights);
for (int i = 1; i <n; i++) {
   if(x[i]==1)
switch (i) {
case 1:
   System.out.print("A\t");
   break;
case 2:
   System.out.print("B\t");
   break;
case 3:
   System.out.print("C\t");
   break;
case 4:
   System.out.print("D\t");
   break;
case 5:
   System.out.print("E\t");
   break;
}
   }
    }
    //背包中物品序号
    public static int[] track(int[][]c,int w[]){
int j = p;
 int[] x = new int[n+1];
 for(int i=n;i>0;i--){
     if(c[i][j]>c[i-1][j]){
     x[i]=1;
     j=j-w[i];
     }else x[i]=0;
    }
 /*for(int m = 1;m<=n;m++){
     System.out.println(x[m]);
 }*/
 return x;
    }
    //0-1背包求解
  public static  int[][] knapsackNp(int[] v,int[] w,int n,int p){
      int [][] c = new int[n+1][p+1];
      //初始化
      for(int i = 0;i<=p;i++){
 c[0][i] = 0;
      }
      for(int i =1;i<=n;i++){
 c[i][0] = 0;
 for(int j = 1;j<=p;j++){
     if(w[i] <= j){
 if((v[i]+c[i-1][j-w[i]])>c[i-1][j]){
     c[i][j] = v[i] + c[i-1][j-w[i]];
 }else{
     c[i][j] = c[i-1][j];
 }
     }else{
 c[i][j] = c[i-1][j];
     }
 }
      }
      return c;
  }
}

结果:

重量为:50 30 45 25 5
价值为:200 180 225 200 50
0-1背包求解最大价值为:605
背包序号为:B C D

二、回朔法

package com.fourwork;


public class Test4 {
    private double[] p, w;// 分别代表价值和重量
    private int n;
    private double c;
    private double bestp;
    private double cp;
    private double cw;
    private int x[]; // 记录可选的物品
    private int[] cx;


    public Test4(double pp[], double ww[], double cc) {
this.p = pp;
this.w = ww;
this.n = pp.length - 1;
this.c = cc;
this.cp = 0;
this.cw = 0;
this.bestp = 0;
x = new int[ww.length];
cx = new int[pp.length];
    }


    void knapsack() {
backtrack(0);
    }


    void backtrack(int i) {
if (i > n) { // 判断是否到达了叶子节点
   if (cp > bestp) {
for (int j = 0; j < x.length; j++)
   x[j] = cx[j];
bestp = cp;
   }
   return;
}
if (cw + w[i] <= c) {// 搜索右子树
   cx[i] = 1;
   cw += w[i];
   cp += p[i];
   backtrack(i + 1);
   cw -= w[i];
   cp -= p[i];
}
cx[i] = 0;
backtrack(i + 1); // 检查左子树
    }


    void printResult() {

for (int i = 0; i < x.length; i++) {
   if(x[i]==1){
System.out.print((char)(65+i)+"\t");
   }
}
    }


    public static void main(String[] args) {
double p[] = { 200,180,225,200,50 };//价值
double w[] = {50,30,45,25,5 };//重量
int maxWeight = 100;
Test4 t = new Test4(p, w, maxWeight);
t.knapsack(); // 回溯搜索
System.out.println("回溯法");
System.out.println("物品个数:n="+p.length);
System.out.println("背包容量:c="+maxWeight);
System.out.println("物品重量:50,30,45,25,5");
System.out.println("物品价值:200,180,225,200,50");
System.out.println("最优值:=" + t.bestp);
System.out.print("装入背包中的物品是: ");
t.printResult();
    }
}

结果为:

回溯法
物品个数:n=5
背包容量:c=100
物品重量:50,30,45,25,5
物品价值:200,180,225,200,50
最优值:=605.0
装入背包中的物品是: B CD

0 0
原创粉丝点击