背包问题:一个给定容量的背包、若干具有一定价值和重量的物品,如何选择物品放入背包的价值最大。其中又分为01背包与完全背包(完全背包指每种物品可以无限件使用)
思路分析:
算法的主要思想,利用动态规划来解决。每次遍历到第i个物品,根据w[i]和v[i]来确定是否需要将该物品放入到背包中。即对给定的n个物品,设v[i]、w[i]分别为第i个物品的价值和重量,C为背包的容量。再令v[i][j]表示在前i个物品中能够装入容量为j的背包的最大价值。
公式:1)v[i][0] = v[0][j] = 0 // 第一行与第一列为0// 当准备加入的商品容量大于当前背包的容量时,就直接使用上一个单元格的装入策略2) 当w[i]>j时,v[i][j] = v[i-1][j]// 当加入的商品小于当前背包的容量时。// 装入的方式为:v[i-1][j] 上一个单元格的装入的最大量// v[i]: 表示当前商品价值 v[i-1][j-w[i]]:装入i-1商品到剩余空间j-w[i]的最大值3) 当j>=w[i]时,v[i][j] = max{v[i-1][j], v[i-1][j-w[i]] + v[i]}
具体的代码实现:
public class KnasackProblem {public static void main(String[] args) {// 解决装包的问题int[] w = {1, 4, 3};int[] val = {1500, 3000, 2000};int m = 4; // 背包的容量int n = val.length;int[][] v = new int[n+1][m+1];int[][] path = new int[n+1][m+1];for(int i=1; i<= n; i++) {for(int j = 1; j <= m; j ++ ) {if(w[i-1] > j) {v[i][j] = v[i-1][j];}else {// v[i][j] = Math.max(v[i-1][j], v[i-1][j-w[i-1]] + val[i-1]);if(v[i-1][j] < v[i-1][j-w[i-1]] + val[i-1]) {path[i][j] = 1;v[i][j] = v[i-1][j-w[i-1]] + val[i-1];}else {v[i][j] = v[i-1][j];}}}}for(int[] num: v) {System.out.println(Arrays.toString(num));}// 输出pathSystem.out.println("==========================");int i = path.length -1;int j = path[0].length - 1;while(i >= 0 && j >= 0) {if(path[i][j] == 1) {System.out.println("装入第" + i + "个物品");j -= w[i-1];}i --;}}}
