一、动态规划法
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