0/1背包和多重背包问题

Given weights and values of n items, put these items in a knapsack of capacity W to get the maximum total value in the knapsack. In other words, given two integer arrays val[0..n-1] and wt[0..n-1] which represent values and weights associated with n items respectively. Also given an integer W which represents knapsack capacity, find out the maximum value subset of val[] such that sum of the weights of this subset is smaller than or equal to W. You cannot break an item, either pick the complete item, or don’t pick it (0-1 property).


Screen Shot 2019-07-29 at 11.35.57 PM.png
// A Dynamic Programming based solution for 0-1 Knapsack problem 
class Knapsack 
{ 
   // Returns the maximum value that can be put in a knapsack of capacity W 
    static int knapSack(int W, int wt[], int val[], int n) 
    { 
         int i, w; 
     int K[][] = new int[n+1][W+1]; 
       
     // Build table K[][] in bottom up manner 
     for (i = 0; i <= n; i++) 
     { 
         for (w = 0; w <= W; w++) 
         { 
             if (i==0 || w==0) 
                  K[i][w] = 0; 
             else if (wt[i-1] <= w) 
                   K[i][w] = Math.max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w]); 
             else
                   K[i][w] = K[i-1][w]; 
         } 
      } 
       
      return K[n][W]; 
    } 
}

0/1背包问题,也可以被应用到求数组sum的问题,https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation
特点:选几个元素,拿到最大,能不能达到之类的。

多重背包问题

有一系列按钮,每个按钮按下去会得到一定体积范围的可乐。先给定一个目标体积范围,问不限制按按钮次数,能否确定一定能得到目标范围内的可乐?
举例:有三个按钮,按下去得到的范围是[100, 120], [200, 240], [400, 410],
假设目标是[100, 110], 那答案是不能。因为按下一,可能得到120体积的可乐,不在目标范围里。
假设目标是[90, 120],那答案是可以。因为按下一,一定可以得到此范围内的可乐。
假设目标是[300, 360], 那答案是可以,因为按下一再按二,一定可以得到此范围内
假设目标是[310, 360], 那答案是不能,因为按下一再按二,有可能得到300,永远没可能确定得到这个范围内的可乐。
假设目标是[1, 9999999999],那答案是可以。随便按一个都确定满足此范围。

public static boolean coke(List<List<Integer>> buttons, List<Integer> target) {
    int m = target.get(0);
    int n = target.get(1);
    boolean[][] dp = new boolean[m + 1][n + 1];
    
    //Init
    for (int i = 0; i <= m; ++i) {
      for (int j = 0; j <= n; ++j) {
        for (List<Integer> button : buttons) {
          if (i <= button.get(0) && j >= button.get(1)) {
            dp[i][j] = true;
            break;
          }
        }
      }
    }
  
    for (int i = 0; i <= m; ++i) {
      for (int j = 0; j <= n; ++j) {
        for (List<Integer> button : buttons) {
          int preL = i - button.get(0);
          int preR = j - button.get(1);
          if (preL >= 0 && preR >= 0 && dp[preL][preR]) {
            dp[i][j] = true;
           break;
          }
        }
      }
    }
    
    return dp[m][n];
  }

多重背包问题:每个可以拿多次,求上下节或者范围之类的,从拿到的数值入手。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,505评论 0 13
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,449评论 0 10
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,906评论 0 38
  • 我们都活在浩瀚的宇宙中,我们都是宇宙中细小的尘埃。即使是那小小的尘埃,却到处可以追寻到生命的根源与顽强。 生命无处...
    牧雨阅读 562评论 0 2
  • 注:文章前半部分是我个人对于现今一些算命行为的看法,后半部分是整理的关于熊逸讲解《周易》的一些内容。当然,大家可以...
    畅谈一下阅读 1,153评论 0 0