【背包问题】——01背包问题

122 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

介绍

有一个容量为 N 的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积 w 和价值 v。

解题模板

// W 为背包总体积
// N 为物品数量
public int knapsack(int W, int N, int[] weights, int[] values) {
    int[] dp = new int[W + 1];
    for (int i = 1; i <= N; i++) {
        int w = weights[i - 1], v = values[i - 1];
        for (int j = W; j >= 1; j--) {
            if (j >= w) {
                dp[j] = Math.max(dp[j], dp[j - w] + v);
            }
        }
    }
    return dp[W];
}

例题1——分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

 

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5][11] 。
示例 2:

输入:num

题目来源:力扣(LeetCode)

思路

1.由于是判断能否将数组分成值相同的两块,所以将数组sum的一半作为背包容量进行计算。

代码

class Solution {
    public boolean canPartition(int[] nums) {
          int sum = 0;
          for(int num:nums){
              sum+=num;
          }
          if(sum%2!=0) return false;
          int w = sum/2;
          boolean[] dp = new boolean[w+1];
          dp[0]=true;
          for(int num:nums){  //外层是物品价值的列举
                for(int i=w;i>=num;i--){ //内层是容量为i的情况
                     dp[i]=dp[i]||dp[i-num];
                }
          }
        return dp[w];
    }
}

例题2——1和0

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

来源:力扣(LeetCode)

思路

1.这是一个多维费用的0,1背包问题,有两个大小0的数量和1的数量

2.依旧是外层循环遍历出每种数量的值,内层循环对dp进行维护

代码

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
      if(strs==null||strs.length==0) return 0;
      int[][] dp = new int[m+1][n+1];
      for(String str:strs){
          char[] chars = str.toCharArray();
          int zero = 0;
          int one =0;
          for(char c:chars){
              if(c=='0'){
                  zero++;
              }else{
                  one++;
              }
          }
          for(int i=m;i>=zero;i--){
              for(int j=n;j>=one;j--){
                  dp[i][j]=Math.max(dp[i-zero][j-one]+1,dp[i][j]);
              }
          }

      }
      return dp[m][n];
    }
}