代码随想录算法训练营第38天| 322. 零钱兑换、279.完全平方数、139.单词拆分

模板:

  • 今日学习的文章链接和视频链接
  • 自己看到题目的第一想法
  • 看完代码随想录之后的想法 
  • 自己实现过程中遇到哪些困难 
  • 今日收获,记录一下自己的学习时长

322. 零钱兑换 

题目链接:322. 零钱兑换 - 力扣(LeetCode)

学习链接:代码随想录

题解:

法一:

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp=[float('inf')]* (amount+1)
        dp[0] = 0
        for i in range(len(coins)):
            for j in range(coins[i],amount+1):
                if dp[j - coins[i]] != float('inf'): 
                    dp[j] = min(dp[j-coins[i]]+1,dp[j])
        if dp[amount] == float('inf'): 
            return -1
        return dp[amount]

完全背包问题(如本题)中,可以用正序遍历,因为每种硬币可以被无限次使用;但如果是0-1 背包问题(每个物品只能选一次),则需要倒序遍历 dp

这题有非常多需要格外注意的地方,比如初始化要设为最大值,因为最后取小。

遍历顺序可以先背包也可以先物品,因为本题不强调是排列还是组合。

如果求组合数就是外层for循环遍历物品,内层for遍历背包。

如果求排列数就是外层for遍历背包,内层for循环遍历物品。

只有不再是最大值的时候 才说明这个值是后面遍历时候可用的。


279.完全平方数

题目链接:279. 完全平方数 - 力扣(LeetCode)

学习链接:代码随想录

题解:

法一:

import math
class Solution:
    def numSquares(self, n: int) -> int:
        l = math.ceil(n ** 0.5)
        nums = [0]*l
        for i in range(l):
            nums[i] = (i+1)**2
        dp = [float('inf')]*(n+1)
        dp[0] = 0

        for num in nums:
            for j in range(num,n+1):
                if dp[j-num] != 'inf':
                    dp[j] = min(dp[j-num]+1,dp[j])
        if dp[n] == 'inf':
            return -1
        return dp[n]

和上一题基本一模一样。


139.单词拆分

题目链接:​​​​​​​139. 单词拆分 - 力扣(LeetCode)

学习链接:​​​​​​​代码随想录

题解:

法一:

class Solution:
    def wordBreak(self, s: str, wordDict: list) -> bool:
        dp = [False] * (len(s) + 1)
        dp[0] = True 
        for i in range(1,len(s)+1):
            for j in range(i):
                if s[j:i] in wordDict and dp[j] is True:
                    dp[i] = True
        return dp[len(s)]

这题完全想不到怎么处理 能理解背包是什么物品是什么 是完全背包 但是不知道该怎么处理。

这个递推思路还是挺值得琢磨的。


动态规划:关于多重背包,你该了解这些!

题目链接:​​​​​​​​​​​​​​56. 携带矿石资源(第八期模拟笔试)

学习链接:​​​​​​​​​​​​​​代码随想录

题解:

c,n = map(int,input().split())
weight = [int(x) for x in input().split(" ")]
value = [int(x) for x in input().split(" ") if x]
limit = [int(x) for x in input().split(" ")]

dp = [0] * (c+1)

dp[0] = 0

for i in range(n):
    for j in range(c,weight[i]-1,-1):
        for k in range(1,limit[i]+1):
            if k*weight[i] > j:
                break
            dp[j] = max(dp[j],dp[j-weight[i]*k]+value[i]*k)
print(dp[-1])

三层遍历 注意最后一层遍历的含义和意义

注意判断条件。

多重背包和普通01背包差别没有非常大

你可能感兴趣的:(算法)