2021-10-19背包问题

背包问题分类:

常见的背包类型主要有以下几种:
1、0/1背包问题:每个元素最多选取一次
2、完全背包问题:每个元素可以重复选择
3、组合背包问题:背包中的物品要考虑顺序
4、分组背包问题:不止一个背包,需要遍历每个背包

而每个背包问题要求的也是不同的,按照所求问题分类,又可以分为以下几种:
1、最值问题:要求最大值/最小值
2、存在问题:是否存在…………,满足…………
3、组合问题:求所有满足……的排列组合

二维动态规划

下面展示一些 二维动态规划

// An highlighted block
public void bags() {
		int[]weight= {1,3,4};
		int[]value= {15,20,30};
		int bagWeight=4;//背包最大承重
		
		// 二维数组:状态定义:dp[i][j]表示从0-i个物品中选择不超过j重量的物品的最大价值
		int[][]dp=new int [weight.length+1][bagWeight+1];
		
		// 初始化:第一列都是0,第一行表示只选取0号物品最大价值
		for (int j = bagWeight; j >= weight[0]; j--)
		        dp[0][j] = dp[0][j - weight[0]] + value[0];
		 
		 // weight数组的大小 就是物品个数
		for (int i = 1; i < weight.length; i++) // 遍历物品(第0个物品已经初始化)
		 {
	        for (int j = 0; j <= bagWeight; j++) // 遍历背包容量
	        {
	            if (j < weight[i])           //背包容量已经不足以拿第i个物品了
	                dp[i][j] = dp[i - 1][j]; //最大价值就是拿第i-1个物品的最大价值
	            //背包容量足够拿第i个物品,可拿可不拿:拿了最大价值是前i-1个物品扣除第i个物品的 重量的最大价值加上i个物品的价值
	            //不拿就是前i-1个物品的最大价值,两者进行比较取较大的
	            else
	            	dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);
	        }
	    }
		int max=dp[weight.length-1][bagWeight];
		for(int []i:dp) {
			System.out.println(" ");
			for(int j:i) {
				System.out.print(j);
				System.out.print(" ");
			}
		}
				
	}

一维优化

dp[j]:容量为j的背包能放下东西的最大价值

// An highlighted block
	public void bags() {
		int[]weight= {1,3,4};
		int[]value= {15,20,30};
		int bagWeight=4;
		
		int[]dp=new int[bagWeight+1];
		for (int i = 0; i < weight.length; i++)
	    { // 遍历物品
	        for (int j = bagWeight; j >= weight[i]; j--)
	        {                                                     // 遍历背包容量(一定要逆序)
	            dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]); //不取或者取第i个
	        }
	    }
		for(int j:dp) {
			System.out.print(j);
			System.out.print(" ");
		}
		
				
	}

分类解题模板

背包问题大体的解题模板是两层循环,分别遍历物品nums和背包容量target,然后写转移方程,
根据背包的分类我们确定物品和容量遍历的先后顺序,根据问题的分类我们确定状态转移方程的写法

首先是背包分类的模板:
1、0/1背包:外循环nums,内循环target,target倒序且target>=nums[i];
2、完全背包:外循环nums,内循环target,target正序且target>=nums[i];
3、组合背包:外循环target,内循环nums,target正序且target>=nums[i];
4、分组背包:这个比较特殊,需要三重循环:外循环背包bags,内部两层循环根据题目的要求转化为1,2,3三种背包类型的模板

然后是问题分类的模板:
1、最值问题: dp[i] = max/min(dp[i], dp[i-nums]+1)或dp[i] = max/min(dp[i], dp[i-num]+nums);
2、存在问题(bool):dp[i]=dp[i]||dp[i-num];
3、组合问题:dp[i]+=dp[i-num];

参考:
作者:eh-xing-qing
链接:https://leetcode-cn.com/problems/last-stone-weight-ii/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-5lfv/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值