背包问题初步总结--01背包,完全背包,有顺序的完全背包
public class TestBeiBao2 {
//常见的背包问题有1、组合问题。2、True、False问题。3、最大最小问题。
//1组合问题:dp[i]+=dp[i-num]
//2true,false问题:dp[i] = dp[i] or dp[i-num]
//3最大最小问题:dp[i] = min(dp[i], dp[i-num]+value[num])或者dp[i] = max(dp[i], dp[i-num]+value[num])
//常见解法
//1分析是否为背包问题
//2是以上三种背包问题中的哪一种
//3是0-1背包问题还是完全背包问题。也就是题目给的nums数组中的元素是否可以重复使用
//4如果是组合问题,是否需要考虑元素之间的顺序。需要考虑顺序有顺序的解法,不需要考虑顺序又有对应的解法
//常见技巧
//1如果是0-1背包,即数组中的元素不可重复使用,nums放在外循环,target在内循环,且内循环倒序;
//2如果是完全背包,即数组中的元素可重复使用,nums放在外循环,target在内循环,且内循环正序;或者target在外循环,nums放在内循环,且内循环正序
//3如果组合问题需考虑元素之间的顺序,需要在上面两者情况中选择一种,记住:当外层循环遍历nums时说明nums只可能按遍历顺序排列
//常见问题
//1典型01背包
//一维数组(滚动数组)01背包
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]);
}
}
for (int i = 0; i <= bagWeight; i++) {
System.out.println(dp[i]);
}
}
@Test
public void test1() {
int[] weight = {1, 3, 4};//重量 2 3 4 5 9
int[] value = {15, 20, 30};//价值3 4 5 8 10
int bagWight = 4;
testWeightBagProblem(weight, value, bagWight);
}
//2典型完全背包
public void testCompletePackAnotherWay(int[] weight, int[] value, int bagWeight) {
int wLen = weight.length;
int[] dp = new int[bagWeight + 1];
//以下两者遍历方式都行
//遍历顺序:先遍历背包,再遍历物品
// for (int i = 1; i <= bagWeight; i++){ // 遍历背包容量
// for (int j = 0; j < weight.length; j++){ // 遍历物品
// if (i - weight[j] >= 0){
// dp[i] = Math.max(dp[i], dp[i - weight[j]] + value[j]);
// }
// }
// }
//遍历顺序:先遍历物品,再遍历背包容量
for (int i = 0; i < wLen; i++) {
for (int j = 1; j <= bagWeight; j++) {//j从0和1都行 因为j=0结果肯定是0(默认值)
if (j >= weight[i]) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
}
for (int i = 0; i <= bagWeight; i++) {
System.out.println(dp[i]);
}
}
@Test
public void test2() {
int[] weight = {1, 3, 4};//重量 2 3 4 5 9
int[] value = {15, 20, 30};//价值3 4 5 8 10
int bagWight = 4;
testCompletePackAnotherWay(weight, value, bagWight);
}
//3有顺序的背包--LeetCode377
//给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
//情况1-顺序不同的组合当做相同的组合
public int combinationSum41(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = 1; j <= target; j++) {
if (j >= nums[i]) {
dp[j] += dp[j - nums[i]];
}
}
}
for (int k = 0; k <= target; k++) {
System.out.println(dp[k]);//1 1 2 3 4
}
return dp[target];
}
@Test
public void test3() {
int[] nums = {1, 2, 3};
int target = 4;
combinationSum41(nums, target);
}
//情况2-顺序相同的组合当做不同的组合
public int combinationSum42(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 0; i <= target; i++) {
for (int j = 0; j < nums.length; j++) {
if (i >= nums[j]) {
dp[i] += dp[i - nums[j]];//1 1 2 4 7
}
}
}
for (int k = 0; k <= target; k++) {
System.out.println(dp[k]);
}
return dp[target];
}
@Test
public void test4() {
int[] nums = {1, 2, 3};
int target = 4;
combinationSum42(nums, target);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了