动态规划七种背包问题白露~

贵有恒何必三更眠五更起最无益只怕一日曝十日寒

动态规划是一种解决复杂问题的方法,它可以将一个问题分解为若干个子问题,然后利用子问题的最优解来构造原问题的最优解。动态规划的核心思想是避免重复计算,即将已经求解过的子问题的结果保存起来,以便后续使用。

背包问题是一类经典的动态规划问题,它描述了一个背包有一定的承重上限,而有若干个物品,每个物品有自己的重量和价值,如何选择装入背包的物品,使得背包内物品的总价值最大。背包问题有很多变种,例如01背包、完全背包、多重背包等,它们都可以用动态规划的方法来求解。

本文将介绍动态规划背包问题的基本概念和思路,并以leetcode里的题目作为案例,给出JAVA实现的答案。本文将涵盖以下几种类型的背包问题:

leetcode上相应的练习题

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

示例1:

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

示例2:

输入:nums=[1,2,3,5]输出:false解释:数组不能分割成两个元素和相等的子集。

这道题可以转化为一个0-1背包问题,即从数组中选取若干个数,使得它们的和等于数组总和的一半。

如果数组总和是奇数,则直接返回false。

如果是偶数,则定义一个二维数组dp[i][j]

二维数组dp[i][j]表示从前i个数中选取若干个数,使得它们的和不超过j的最大值。则状态转移方程为:

dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])

其中,dp[i-1][j]表示不选第i个数,dp[i-1][j-nums[i]]+nums[i]表示选第i个数。最后判断dp[n][sum/2]是否等于sum/2即可。

classSolution{publicbooleancanPartition(int[]nums){//数组总和intsum=0;for(intnum:nums){sum+=num;}//如果总和是奇数,则不能分割成两个相等的子集if(sum%2==1){returnfalse;}//数组长度intn=nums.length;//dp数组int[][]dp=newint[n+1][sum/2+1];//初始化第一行为0for(intj=0;j<=sum/2;j++){dp[0][j]=0;}//遍历物品for(inti=1;i<=n;i++){//遍历容量for(intj=0;j<=sum/2;j++){//不选第i个数dp[i][j]=dp[i-1][j];//如果容量大于等于第i个数,可以选择选或不选if(j>=nums[i-1]){dp[i][j]=Math.max(dp[i][j],dp[i-1][j-nums[i-1]]+nums[i-1]);}}}//判断是否能分割成两个相等的子集returndp[n][sum/2]==sum/2;}}复杂度

题目:

给你一个整数数组nums和一个整数target。向数组中的每个整数前添加'+'或'-',然后串联起所有整数,可以构造一个表达式:

例如,nums=[2,1],可以在2之前添加'+',在1之前添加'-',然后串联起来得到表达式"+2-1"。返回可以通过上述方法构造的、运算结果等于target的不同表达式的数目。

输入:nums=[1,1,1,1,1],target=3输出:5解释:一共有5种方法让最终目标和为3。-1+1+1+1+1=3+1-1+1+1+1=3+1+1-1+1+1=3+1+1+1-1+1=3+1+1+1+1-1=3示例2:

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

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

输入:strs=["10","0001","111001","1","0"],m=5,n=3输出:4解释:最多有5个0和3个1的最大子集是{"10","0001","1","0"},因此答案是4。其他满足题意但较小的子集包括{"0001","1"}和{"10","1","0"}。{"111001"}不满足题意,因为它含4个1,大于n的值3。示例2:

和LeetCode322是类似的一道题

给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount,表示总金额。

计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回0。

假设每一种面额的硬币有无限个。

题目数据保证结果符合32位带符号整数。

输入:amount=5,coins=[1,2,5]输出:4解释:有四种方式可以凑成总金额:5=55=2+2+15=2+1+1+15=1+1+1+1+1

示例3:

输入:amount=10,coins=[10]输出:1

这道题可以转化为一个完全背包问题,即从coins数组中选取若干个数,使得它们的和等于amount。定义一个一维数组dp[j]表示容量为j的背包可以装入的硬币组合数。则状态转移方程为:

dp[j]=dp[j]+dp[j-coins[i]]

其中,dp[j]表示不选第i种硬币,dp[j-coins[i]]表示选第i种硬币。注意这里是加号,因为要求所有可能的组合数。最后返回dp[amount]即可。

空间复杂度:O(amount),需要创建一个一维dp数组。

计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1。

你可以认为每种硬币的数量是无限的。

输入:coins=[1,2,5],amount=11输出:3解释:11=5+5+1

输入:coins=[2],amount=3输出:-1

输入:coins=[1],amount=0输出:0

这道题可以转化为一个多重背包问题,即从coins数组中选取若干个数,使得它们的和等于amount,且每种硬币有有限个。定义一个一维数组dp[j]表示容量为j的背包可以装入的最少硬币个数。则状态转移方程为:

dp[j]=min(dp[j],dp[j-coins[i]]+1)

其中,dp[j]表示不选第i种硬币,dp[j-coins[i]]+1表示选第i种硬币。注意这里是最小号,因为要求最少的硬币个数。最后判断dp[amount]是否等于初始值,如果是则返回-1,否则返回dp[amount]。

背包问题是一类常见的动态规划问题,它的核心思想是定义一个合适的状态表示和状态转移方程,然后根据问题的要求进行初始化和遍历。在解决背包问题时,需要注意以下几点:

THE END
1.动态规划之01背包问题(最易理解的讲解)01背包问题,是用来介绍动态规划算法最经典的例子,网上关于01背包问题的讲解也很多,我写这篇文章力争做到用最简单的方式,最少的公式把01背包问题讲解透彻。 01背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] } https://blog.csdn.net/mu399/article/details/7722810
2.01背包问题算法详解(动态规划)四 复杂度 显然算法空间复杂度与时间复杂度均为O(n*m)。其中m为背包容量。 五 总结 用动态规划算法解决0-1背包问题相较于暴力求解法时间复杂度大大降低,理解关键在于状态转移方程的推演过程。https://www.jianshu.com/p/31885390fa5f
3.Python中的背包问题:3种解决的算法实现星星猫的技术博客注意:请记住,这些约束可能会根据您的问题陈述而更改。 解决背包问题的不同方法 Python 以下3 种方法是解决 Python 中背包问题的可用方法—— 贪婪算法 动态规划算法 蛮力算法 贪婪算法 classKnapsackPackage(object):""" Knapsack Package Data Class """def__init__(self,weight,value):self.weight=weight https://blog.51cto.com/u_14249042/10451210
4.C++01背包问题Hello算法(C++版)首页 / Hello 算法(C++版) / C++0-1背包问题 C++0-1背包问题背包问题是一个非常好的动态规划入门题目,是动态规划中最常见的问题形式。其具有很多变种,例如 0-1 背包问题、完全背包问题、多重背包问题等。 在本节中,我们先来求解最常见的 0-1 背包问题。 Question 给定n 个物品,第 i 个物品的重量为 wgthttps://m.w3cschool.cn/hellocpp/hellocpp-y2gz3tli.html
5.基于猴群算法求解0背包问题已成为众多学者研究的一个热点问题, 寻找新的方法来求解背包问题具有重要的理论和实际意义[3]. 目前, 求解背包问题的方法主要有两种: 最优算法和启发式算法. 最优算法包括穷举法、动态规划法、递归算法、回溯法和分支界限法等[4–7]. 启发式算法包括差分进化算法[8], 粒子群算法[9]和遗传算法[10]等.https://c-s-a.org.cn/html/2018/5/6340.html
6.动态规划背包问题合集背包系列作为动态规划问题中的经典,一直是新手村的精英BOSS。通过这几天的学习,对出现的一些背包系列进行总结归纳,希望对大家有所帮助。 背包问题 问题描述:给定N个物品和一个容量有限为V的背包,每个物品有两种属性:v[i](该物品的体积) 和 w[i](该物品的价值,即权重),求解在不超过背包最大容量的情况下,能装https://leetcode.cn/circle/discuss/u9jlGz/
7.2024.11.28DailyProblem考虑4种转移: 有r×cn×n的概率,dpr,c→dpr,c 有(n?r)×cn×的概率,dpr+1,c→dpr,c 有r×(n?c)n×n的概率,dpr,c+1→dpr,c 有(n?r)×(n?c)n×n的概率,dpr+1,c+1→dpr,c 可以考虑记忆化搜索,然后转移式子注意移项解决环依赖的问题。 https://zhuanlan.zhihu.com/p/9667603218
8.动态规划专题刷题记录③:背包问题腾讯云开发者社区问题的名称来源于如何选择最合适的物品放置于给定背包中。常见的背包问题有:01背包,完全背包,多重背包,分组背包,混合背包,有依赖的背包问题等,考察方向一般为求最优解、最优方案数、最优方案。下面会分别介绍这几种背包问题的分析方法和例题。 本文所有例题均来自:Acwing 算法提高课https://cloud.tencent.com/developer/article/2034056
9.java动态规划算法——硬币找零问题实例分析java这篇文章主要介绍了java动态规划算法——硬币找零问题,结合实例形式分析了java动态规划算法——硬币找零问题相关原理、实现方法与操作注意事项,需要的朋友可以参考下本文实例讲述了java动态规划算法——硬币找零问题。分享给大家供大家参考,具体如下:问题描述现在有3种硬币分别为:1元,5元,10元,现在给你63元,让你全部https://www.jb51.net/article/187327.htm