动态规划算法之背包问题

物品 重量(磅) 价格
吉他(G) 2 1500
音响(S) 4 5000
电脑(L) 5 2000
  1. 装入的背包的总价值最大,并且重量不超出
  2. 装入的物品不能重复

算法介绍

  1. 动态规划核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解
  2. 动态规划与分治算法类似,基本思想也是将待求解问题分解成若干子问题,先求子问题,然后从这些子问题的解得到原问题的解
  3. 与分治法不同,适合于动态规划求解的问题,经分解得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)
  4. 动态规划算法可以通过填表的方式来逐步推进,得到最优解

背包问题

  1. 给定容量的背包,若干具有一定价值和重量的物品。如何选择物品使放入背包的物品价值最大。其中又分为01背包和完全背包(每种物品都有无限件可用)
  2. 这里的问题属于01背包,即每种物品最多放一个(0个或1个),无限背包可以转化为01背包

背包问题思路

  1. 每次遍历第i个物品,设W[i]和V[i]分别第i个物品的价值和重量

  2. v[i] [j] 表示在前i的物品中能够放入容量为j的背包的价值最大值

    1磅 2磅 3磅 4磅
    吉他 1500 1500 1500 1500
    音响 1500 1500 1500 3000
    电脑 1500 1500 2000 2000+1500
  • w[i]>j时,v[i] [j] = v[i-1] [j] //当前加入的物品容量大于背包容量,则取遍历到上一个物品时的最大装入策略
  • w[i]<=j时,v[i] [j] = max(v[i-1] [j], v[i-1] [j-w[i]] + V[i])
public class DynamicProgramming {

  public static void main(String[] args) {
    int[] w = {1, 4, 3}; // 物品的重量
    int[] val = {1500, 3000, 2000}; // 物品的价值
    int m = 4; // 背包的容量

    // 多垫一行一列,避免数组越界
    int[][] v = new int[w.length + 1][m+1]; // v[i][j] 表示前i个物品能够装容量为j的背包的最大价值
    // 因为多垫了一行一列,所以下标从1开始
    for (int i = 1; i < v.length; i++) {
      for (int j = 1; j < v[0].length; 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]);
        }
      }
    }

    printV(v);
  }

  public static void printV(int[][] v) {
    for (int[] val : v) {
      System.out.println(Arrays.toString(val));
    }
  }

}

你可能感兴趣的:(动态规划算法之背包问题)