⼒扣刷题-python-动态规划-1(动态规划、01背包问题、完全背包问题)⽂章⽬录
1.动态规划
动态规划 是由前⼀个状态推导出
贪⼼算法 是直接取局部最优
动态规划需要直到状态转移公式
解题过程分为5步
1. 确定dp数组(dp table)以及下标的含义
2. 确定递推公式
3. dp数组如何初始化
4. 确定遍历顺序
5. 举例推导dp数组
2.简单和中等题
其实也不⽤写dp数组,这道题就可以解出来,但是这道题还是⽤了动态规划的思想,每个数之间是有关系的这道题同上⼀道题
进阶版的爬楼梯class Solution: def fib (self, n: int ) -> int: if n <2:return n a, b = 0, 1 for i in range (n-1): a =a+b a,b =b,a return b
1
2
3
4
5
6
7
8class Solution: def climbStairs (self, n: int ) -> int: #每次爬台阶相当于是 n-1情况 和n-2情况和, dp =[] for i in range (n ): if i <2: dp.append (i+1) else: dp [0]+=dp [1] dp [0],dp [1]=dp [1],dp [0] return dp [-1]
1
2
3
4
5
6
7
8
9
10
这道题和爬楼梯类似,不过是⼀个⼆维的
这道题的确不好想,⽽且 是个⼆维的循环,以后在动态规划,可能会经常⽤到。class Solution: def minCostClimbingStairs (self, cost: List [int ]) -> int: #dp[i]为某⼀层花费 dp[i] =min(dp[i-1] dp[i-2])+cost[i] #dp[0]=1 dp[1]=100 dp = [0]*len (cost ) #提前配置好空间,再赋值会快很多 for i in range (len (cost )): if i <2: dp [i ]=cost [i ] else:dp [i ]= min (dp [i-1],dp [i-2]) + cost [i ] return min (dp [-2:])
1
2
3
4
5
6
7
8
9
10class Solution: def uniquePaths (self, m: int, n: int ) -> int: #第mn ⾏肯定是 第m-1 n ⾏ 和第m n-1⾏移动过来的 #dp 表⽰mn 位置的条数 dp[m][n] #初始化 m=0位置为1 n=0位置为1 因为边上只有⼀条路径可以⾛ dp = [[1]*n for _ in range (m )] for i in range (1,m ): for j in range (1,n ): dp [i ][j ]=dp [i-1][j ] + dp [i ][j-1] return dp [-1][-1]
1
2
3
4
5
6
7
8
9
10class Solution: def uniquePathsWithObstacles (self, obstacleGrid: List [List [int ]]) -> int: #同前⼀道题,但是加⼊了障碍物,所以要将障碍物位置变为0, dp = obstacleGrid for i in range (len (dp )): for j in range (len (dp [0])): if not dp [i ][j ]-1: dp [i ][j ]=0 elif not i and not j :dp [i ][j ]=1 else: dp [i ][j ] =(dp [i-1][j ] if i >0 else 0)+(dp [i ][j-1] if j >0 else 0) return dp [-1][-1]
1
2
3
4
5
6
7
8
910class Solution: def integerBreak (self, n: int ) -> int: #第n 个 相当于 第n 分解成 n-i 和i 乘积 和dpn-i 和i 乘积⽐较 选最⼤的 #虽然n 是从2开始的 相当于只有n-2+1 个 但是为了遍历⽅便扩充成n 个 dp = [_+1 for _ in range (n )] for i in range (n ): for j in range (1,i ): dp [i ] = max (dp [i ] , max (dp [i-j ]*j,(i-j )*j )) #print(dp) return dp [-1] if n >=4 else n-1
1
2
3
4
5
6
7
8
9
10
3.01背包问题基础class Solution: def numTrees (self, n: int ) -> int: #dp 为n 情况下⼆叉搜索树的个数 #dp[i] +=dp[i-j-1]dp[j] for j in range(i) dp = [0]*(n+1) for i in range (n+1): if i < 2: dp [i ]=1 else: for j in range (i ):dp [i ] +=dp [i-j-1]*dp [j ] #print(dp) return dp [-1]
1
2
3
4
5
6
7
8
python 定义数组9
10
11
12
1.01背包基础
背包问题是个啥,我⼀直很好奇,今天终于看到这⾥了,先看下基础理论。# -*- coding: gbk -*-#暴⼒解法nmax =3nlist =[15,20,30]nweigt =[1,3,4]res = []def backtracking (n,weight,hw ): if not n - nmax :return res.append (hw ) for i in [0,1]: if i: #选择 hw += nlist [n-1] weight-=nweigt [n-1] backtracking (n+1,weight,hw ) backtracking (1,4,0)print ('所有可能的情况为:',res )print ('可以放⼊最⼤为:',max (res ))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
暴⼒解法肯定是不可取的,⽤的时间为o(2^n)当这个物体n特别多的时候,这样就太浪费时间了,肯定暴⼒的⽅法是不可取的2.01背包问题的动态规划(⼆维数组)
1)定义
2)递推关系
如果某⼀⾏ 即某⼀个物品i 在j⼩于weight[i]时候,直接取 dp[i-1][j]
如果⼤于weight[i]时候,就可以⽐较他放⼊与不放⼊的总重量的⼤⼩,肯定选最⼤的那个
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
3)初始化
全部初始化为0,但是每次都是和i-1⽐较,所以要初始化i=0⾏
4)遍历顺序
选择⼀⾏⼀⾏遍历,就是⼀个物品⼀个物品来
5)对⽐dp数组并修改程序
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论