「这是我参与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];
}
}