动态规划(09)

87 阅读1分钟

Day14 01背包

1、01背包

  • 题意:体积为w[i]将至为v[i]的物品装到体积为N的背包中,要求价值最大。
  • 思路:
    1. 回溯。将所有的物品依次放入,当达到背包容量时,记录当前的最大价值,然后回溯。ans取每次回溯记录结果的最大值
    2. 动态规划。
      • 最大价值,需要考虑在N容量的背包放入哪几个物品。即状态为容量物品
      • 在容量和物品的状态中,每次有两种状态装进背包未装进背包
      • 综上:
        • 定义DP数组dp[i][j]表示前i个物品装进容量为j的背包的最大价值
        • dp[i][j]=max[dp[i1][j],dp[i1][jweight[i]]+value[i]]dp[i][j]=max[dp[i-1][j],dp[i-1][j-weight[i]]+value[i]]
      • coding
      int knapsack(int W, int N, int[] wt, int[] val) {
          int N == wt.length;
          // base case 已初始化
          int[][] dp = new int[N][W];
          for (int i = 0; i < N; i++) {
              for (int w = 0; w < W; w++) {
                  if (w - wt[i - 1] < 0) {
                      // 这种情况下只能选择不装入背包
                      dp[i][w] = dp[i - 1][w];
                  } else {
                      // 装入或者不装入背包,择优
                      dp[i][w] = Math.max(
                          dp[i - 1][w - wt[i-1]] + val[i-1], 
                          dp[i - 1][w]);
                  }
              }
          }
      
          return dp[N][W];
      }
      
    3. 优化。
      • 根据二维DP的填补过程,dp[i][j]只跟dp[i1][j],dp[i1][jweight[i]]dp[i-1][j],dp[i-1][j-weight[i]]有关
      • dp[i]相当于将dp[i-1]进行copy选择
       public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
           int wLen = weight.length;
           //定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
           int[] dp = new int[bagWeight + 1];
           //遍历顺序:先遍历物品,再遍历背包容量
           for (int i = 0; i < wLen; i++){
               for (int j = bagWeight; j >= weight[i]; j--){
                   dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
               }
           }
           //打印dp数组
           for (int j = 0; j <= bagWeight; j++){
               System.out.print(dp[j] + " ");
           }
       }