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]
lastStoneWeightII

494:目标和

链接:494. 目标和 - 力扣(LeetCode)

 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]
findTargetSumWays

474:1和0

链接:474. 一和零 - 力扣(LeetCode)

 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]
findMaxForm

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])
climbStairs2

🤯🤯🤯完全背包🤯🤯🤯

一个物品可以使用无数次

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。
小明的行李空间为 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)
View Code

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]
change

377:组合总和IV

链接:377. 组合总和 Ⅳ - 力扣(LeetCode)

 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]
combinationSum4

518和377区别:

先遍历背包:排列数,有序;后遍历背包:组合数,无序

322:零钱兑换

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

 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]
coinChange

279:完全平方数

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

 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]
numSquares

139:单词拆分

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

 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                 
wordBreak

 

posted @ 2024-02-22 16:07  小小小茹茹  阅读(13)  评论(0编辑  收藏  举报