Leetcode刷题第十二天-动态规划
1049:最后一块石头的重量II
链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)
1 class Solution: 2 def lastStoneWeightII(self, stones: List[int]) -> int: 3 #dp[i]背包为i的最大价值为dp[i] 4 #推导公式dp[i]=max(dp[i], dp[i-stones[i]]+stones[i]) 5 #dp数组初始化dp=[0]*1501 6 #遍历顺序:背包倒序 7 #打印dp数组 8 sums=sum(stones) 9 num=sums//2 10 dp=[0]*1501 11 for stone in stones: 12 for i in range(num,stone-1,-1): 13 dp[i]=max(dp[i],dp[i-stone]+stone) 14 return sums-2*dp[num]
494:目标和
1 class Solution: 2 def findTargetSumWays(self, nums: List[int], target: int) -> int: 3 #dp[i]背包为i装满i有dp[i]方法 4 #推导公式dp[i]+=dp[i-nums[j]](j:0--len(nums)) 5 #dp数组初始化dp=[1] 6 #遍历顺序:背包倒序 7 #打印dp数组 8 sums=sum(nums) 9 if((sums+target)%2): return 0 10 num=(sums+target)//2 11 dp=[0]*1001 12 dp[0]=1 13 for n in nums: 14 for i in range(num,n-1,-1): 15 dp[i]+=dp[i-n] 16 return dp[num]
474:1和0
1 class Solution: 2 def findMaxForm(self, strs: List[str], m: int, n: int) -> int: 3 #dp[i][j]背包为i,j最大价值 4 #推导公式dp[i][j]=max(dp[i][j],dp[i-x][j-y]+1) 5 #dp数组初始化dp=[1] 6 #遍历顺序:倒序 7 #打印dp数组 8 dp=[[0 for i in range(n+1)] for j in range(m+1)] 9 for s in strs: 10 x=s.count('0') 11 y=s.count('1') 12 for i in range(m,x-1,-1): 13 for j in range(n,y-1,-1): 14 dp[i][j]=max(dp[i][j],dp[i-x][j-y]+1) 15 return dp[m][n]
01背包最大价值推到公式:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]),正序遍历
降低维度:dp[j] = max(dp[j], dp[j - w[i]] + v[i]),倒序遍历背包
01背包装满的方法个数:dp[i]+=dp[i-nums[j]](j:0--len(nums)),倒序
牛客跳台阶扩展
链接:跳台阶扩展问题_牛客题霸_牛客网 (nowcoder.com)
递推公式:dp[i] += dp[j](j:0---i)
1 import sys 2 3 for line in sys.stdin: 4 a = line.split() 5 n = int(a[0]) 6 dp = [0] * (n + 1) 7 if n < 3: 8 print(n) 9 break 10 dp[0], dp[1], dp[2] = 1, 1, 2 11 for i in range(3, n + 1): 12 for j in range(i): 13 dp[i] += dp[j] 14 print(dp[n])
🤯🤯🤯完全背包🤯🤯🤯
一个物品可以使用无数次
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。
输入描述
第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。
第二行包含 M 个正整数,代表每种研究材料的所占空间。
第三行包含 M 个正整数,代表每种研究材料的价值。
1 #dp[i][j]空间大小为i得背包可以放入材料得最大价值 2 #推导公式dp[j]=max(dp[j],dp[j-w[i]]+v[i]) 3 #dp数组初始化 4 #遍历顺序:正序遍历背包 5 #打印dp数组 6 def bag1(m,n,w,v): 7 dp=[0 for j in range(n+1)] 8 for i in range(m): 9 for j in range(w[i],n+1): 10 dp[j] = max(dp[j], dp[j - w[i]] + v[i]) 11 print(dp[n]) 12 m,n=map(int,input().strip().split(' ')) 13 w,v=[],[] 14 for i in range(m): 15 a,b=map(int,input().strip().split(' ')) 16 w.append(a) 17 v.append(b) 18 bag1(m,n,w,v)
518:零钱兑换II
链接:518. 零钱兑换 II - 力扣(LeetCode)
1 class Solution: 2 def change(self, amount: int, coins: List[int]) -> int: 3 #dp[i]背包i装满的方法数 4 #推导公式dp[i]+=dp[i-coins[j]] 5 #dp数组初始化 6 #遍历顺序:正序遍历背包 7 #打印dp数组 8 #组合,无序 9 dp=[0]*(amount+1) 10 dp[0]=1 11 #先物品后背包,组合;先背包后物品,排列 12 for coin in coins: 13 for i in range(amount+1): 14 if(i-coin>=0): dp[i]+=dp[i-coin] 15 return dp[amount]
377:组合总和IV
1 class Solution: 2 def combinationSum4(self, nums: List[int], target: int) -> int: 3 #dp[i]背包i装满的方法数 4 #推导公式dp[i]+=dp[i-nums[j]] 5 #dp数组初始化 6 #遍历顺序:正序遍历背包 7 #打印dp数组 8 #排列 9 dp=[0]*(target+1) 10 dp[0]=1 11 for i in range(target+1): 12 for num in nums: 13 if(i-num>=0): dp[i]+=dp[i-num] 14 return dp[target]
518和377区别:
先遍历背包:排列数,有序;后遍历背包:组合数,无序
322:零钱兑换
1 import sys 2 class Solution: 3 def coinChange(self, coins: List[int], amount: int) -> int: 4 #dp[i]背包i装满最少物品个数 5 #推导公式dp[i]=min(dp[i-con[j]]+1,dp[i]) 6 #dp数组初始化 7 #遍历顺序:正序遍历背包 8 #打印dp数组 9 dp=[float('inf')]*(amount+1) 10 dp[0]=0 11 for coin in coins: 12 for i in range(coin,amount+1): 13 if(dp[i-coin]!=float('inf')): dp[i]=min(dp[i],dp[i-coin]+1) 14 if(dp[amount]==float('inf')): return -1 15 return dp[amount]
279:完全平方数
1 class Solution: 2 def numSquares(self, n: int) -> int: 3 #dp[i]满足i的最少整数个数 4 #推导公式dp[i]=min(dp[i-j*j]+1,dp[i]) 5 #dp数组初始化 6 #遍历顺序:正序遍历背包 7 #打印dp数组 8 dp=[float('inf')]*(n+1) 9 dp[0]=0 10 for i in range(n+1): 11 #j的范围如果直接到i会超时,遍历到i的平方根整数部分即可 12 for j in range(1,int(i**0.5)+ 1): 13 dp[i]=min(dp[i-j*j]+1,dp[i]) 14 return dp[n]
139:单词拆分
1 class Solution: 2 def wordBreak(self, s: str, wordDict: List[str]) -> bool: 3 #dp[i]字符串长度为i能否拆成worddict中的字符 4 #推导公式dp[i]=strs[j:i]in worddict and dp[j] 5 #dp数组初始化 6 #遍历顺序:正序遍历背包 7 #打印dp数组 8 n=len(s) 9 dp=[False] *(n+1) 10 dp[0]=True 11 for i in range(1,n+1): 12 for j in range(i): 13 if(dp[j] and s[j:i] in wordDict): 14 dp[i]=True 15 break 16 return dp[n] 17 18