一些背包问题
01背包问题
题目描述
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。
输入描述
第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。 第二行包含 M
个正整数,代表每种研究材料的所占空间。 第三行包含 M 个正整数,代表每种研究材料的价值。
输出描述
输出一个整数,代表小明能够携带的研究材料的最大价值。
/**
使用二维数组
**/
import java.util.*;public class Main {public static void main(String[] args) {//dp数组含义 dp[i][j] 下标是0-i的物品任取,放进容量是j的物品//递推公式//dp[i][j] 容量为j时// 不妨物品i: dp[i-1][j]// 妨物品i : dp[i-1][j-weight[i]] + value[i];// 背包容量 N// 物品种类 MScanner sc = new Scanner(System.in);int M = sc.nextInt();int N = sc.nextInt();int[] values = new int[M];int[] weights = new int[M];for(int i = 0; i < M;i++) {weights[i] = sc.nextInt();}for(int i = 0; i < M;i++) {values[i] = sc.nextInt();}int[][] dp = new int[M][N+1];// 初始化//如果第一个weights,大于最大容量,则还是0for(int i = weights[0]; i <= N; i++) {dp[0][i] = values[0];}// 先物品for(int i = 1; i < M; i++) {// 后背包容量for(int j = 0; j <= N; j++) {if(weights[i] > j) {//i的重量大于背包容量,只能没法放了,取i-1最大值dp[i][j] = dp[i-1][j];} else {//i的重量小于于背包容量//可方可不妨,取放或者不妨再容量j的条件下的最大值dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weights[i]] + values[i]);}}}System.out.println(dp[M-1][N]);}
}/**
一维数组(滚动数组)
**/import java.util.*;public class Main {public static void main(String[] args) {//dp数组含义 dp[i][j] 下标是0-i的物品任取,放进容量是j的物品//递推公式//dp[i][j] 容量为j时// 不妨物品i: dp[i-1][j]// 妨物品i : dp[i-1][j-weight[i]] + value[i];// 背包容量 N// 物品种类 MScanner sc = new Scanner(System.in);int M = sc.nextInt();int N = sc.nextInt();int[] values = new int[M];int[] weights = new int[M];for(int i = 0; i < M;i++) {weights[i] = sc.nextInt();}for(int i = 0; i < M;i++) {values[i] = sc.nextInt();}int wLen = weights.length;//定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值int[] dp = new int[N + 1];//遍历顺序:先遍历物品,再遍历背包容量for (int i = 0; i < wLen; i++){//倒序遍历是为了保证物品i只被放入一次!for (int j = N; j >= weights[i]; j--){dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]);}}System.out.println(dp[N]);}
}
- 分割等和子集
class Solution {public boolean canPartition(int[] nums) {int len = nums.length;int sum = 0;for(int ele : nums){sum += ele;}if(!(sum %2 ==0)) return false;int target = sum/2;//dp[i] 重量等于价值//dp[target] == target;//推导公式//dp[j] = Math.max(dp[j] ,dp[j-nums[i]]+nums[i])int[] dp = new int[target+1];dp[0]=0;for(int i =0;i<len;i++){for(int j=target;j>=nums[i];j--){dp[j] = Math.max(dp[j] ,dp[j-nums[i]]+nums[i]);}}return dp[target] == target;}
}