算法# 学习目标:动态规划算法(五 )
学习内容:
动态规划算法:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
在查找有很多重叠子问题的情况的最优解有效。动态规划保存子问题的解,避免重复计算。
学习产出:
背包问题:一种组合优化的NP完全问题;0-1背包对物品迭代放外层,里层体积或价值逆向遍历;完全背包物品迭代放里层,外层体积或价值正向遍历
动态规划
解决动态规划问题的关键是找到状态转移方程,这样就可以通过计算和存储子问题的解来解决最终问题。
LeetCode416 分割等和子集
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
0-1背包问题,设数字总和为sum,我们的目标选取一部分物品是的总和sum/2.由于不需要考虑价值,因此布尔矩阵表示状态转移矩阵
代码(python)
class Solution:
def canPartition(self, nums: List[int]) -> bool:
accumulate = sum(nums)
target, n = accumulate//2,len(nums)
if accumulate % 2: return False
dp = [False]*(target+1)
dp[0] = True
for i in range(1,n+1):
for j in range(target,nums[i-1]-1,-1):
dp[j] = dp[j] or dp[j-nums[i-1]]
return dp[target]
LeetCode322 零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
完全背包问题,定义dp[j]表示填满容量为j的背包最少需要多少硬币,状态转移方程:dp[j] = min(dp[j], dp[j - coin] + 1)即当前填满容量j最少需要的硬币 = min( 之前填满容量j最少需要的硬币, 填满容量 j - coin 需要的硬币 + 1个当前硬币)
注意初始化:amount+2矩阵,因为有求最小值,赋值-1会导致结果为-1,同时amount+2大于所有可能组合方式
代码(python)
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [amount+2]*(amount+1)
dp[0] = 0
for i in range(1,amount+1):
for coin in coins:
if i >= coin:
dp[i] = min(dp[i],dp[i-coin]+1)
if dp[amount] == amount+2:
return -1
else:
return dp[amount]
&spm=1001.2101.3001.5002&articleId=115048333&d=1&t=3&u=4fdb12c6cafa4ae9b4faeb9484d8df41)
2万+

被折叠的 条评论
为什么被折叠?



