public class Demo1 { private static int c = 10; //背包容量 private static int[] w= {0,2,2,6,5,5}; //每个物体的重量:5个物体 private static int[] v = {0,6,3,5,4,6}; //每个物体的价值 private static int[] x= new int[6]; //存放每个物体的选中情况 private static int bestcp = 0; //当前的最优解 private static int[] bestcpArr = new int[6]; private static int count = 0; private static int n = 5; //物体的数目 public static void main(String[] args) { backtrack(1, 0 ,0); for(int i =0 ; i < bestcpArr.length ;i++){ System.out.print(bestcpArr[i]); } System.out.println(""); System.out.println(bestcp); System.out.println("该树有" + count +"种遍历方式"); } /** * * @param i:查找到了第i个物品(i从1开始索引) * @param cv:当前包中价值 * @param cw:当前包中重量 */ private static void backtrack(int i , int cw , int cv) { count++; if (i > n) { if (cv > bestcp) { bestcp = cv; for(int j = 0 ; j < 6 ;j++){ bestcpArr[j]= x[j]; } } }else{ // 开始遍历,如果k=0,则表示不装下此物品,k=1,则表示装下此物品 for(int k = 0 ; k <= 1; k++){ x[i] = k; if (cw + w[i] <= c) { cv += v[i] * k; cw +=w[i] * k; backtrack(i + 1, cw, cv); cv -= v[i] * k; cw -=w[i] * k; } } } } }
/**
* 本算法的上界函数是这样定义的!首先利用冒泡法排序,按照单位价值右高到低开始顺序排列!
* 这样的话,就能保证,先装进去的是性价比(自己发明的,勿喷)最优的!而在上界函数中,也是如此,求的是剩余
* 容量在右子树所能容纳的最高价值(背包容量允许情况下),一旦小于当前最优解,那么就
* 没有继续遍历该右子树的必要
*
*/
public class Demo2 { private static int n;// 物品数量 private static double c;// 背包容量 private static double[] v = new double[100];// 各个物品的价值 private static double[] w = new double[100];// 各个物品的重量 private static double cw = 0.0;// 当前背包重量 private static double cp = 0.0;// 当前背包中物品价值 private static double bestp = 0.0;// 当前最优价值 private static double[] perp = new double[100];// 单位物品价值排序后 private static int order[] = new int[100];// 物品编号 private static int[] put = new int[100];// 设置是否装入 // 按单位价值排序 private static void knapsack() { int i, j; int temporder = 0; double temp = 0.0; for (i = 1; i <= n; i++) perp[i] = v[i] / w[i]; for (i = 1; i <= n - 1; i++) { for (j = i + 1; j <= n; j++) if (perp[i] < perp[j])// 冒泡排序perp[],order[],sortv[],sortw[] { temp = perp[i]; perp[i] = perp[i]; perp[j] = temp; temporder = order[i]; order[i] = order[j]; order[j] = temporder; temp = v[i]; v[i] = v[j]; v[j] = temp; temp = w[i]; w[i] = w[j]; w[j] = temp; } } } // 回溯函数 private static void backtrack(int i) { if (i > n) { bestp = cp; return; } // 将物品装进背包:此种情况的话 if (cw + w[i] <= c) { cw += w[i]; cp += v[i]; put[i] = 1; backtrack(i + 1); cw -= w[i]; cp -= v[i]; } if (bound(i + 1) > bestp)// 符合条件搜索右子数 backtrack(i + 1); } // 计算上界函数
//算法剩余容量的情况下最多能装的价值 private static double bound(int i) { double leftw = c - cw; double b = cp; while (i <= n && w[i] <= leftw) { leftw -= w[i]; b += v[i]; i++; } if (i <= n) b += v[i] / w[i] * leftw; return b; } public static void main(String[] args) { // private static int[] w= {0,2,2,6,5,5}; //每个物体的重量:5个物体 // private static int[] v = {0,6,3,5,4,6}; //每个物体的价值 v[0] = 0; v[1] = 6; v[2] = 3; v[3] = 5; v[4] = 4; v[5] = 6; w[0] = 0; w[1] = 2; w[2] = 2; w[3] = 6; w[4] = 5; w[5] = 5; n = 5; c = 10; knapsack(); backtrack(1); System.out.println(bestp); for (int i = 1; i <= n; i++) { System.out.print(put[i] + " "); } System.out.println(""); } }