数据结构与算法习题部分:动态规划、贪婪算法

朱雀 2022-01-31 23:19 331阅读 0赞

一、动态规划
定义:动态规划是指如果我们要求一个问题的最优解,而且该问题可以分解成若干个子问题,并且问题之间还有重叠的更小的子问题,我们就可以考虑用动态规划去解决这个问题。
解决动态规划的问题有四个特点:
1、 我们在应用动态规划之前要分析能否把大问题分解成小问题,如果分解的每个小问题也存在最优解,那么把这些小问题的最优解组合起来就能够得出这个问题的最优解,我们就可以应用动态规划解决这个问题
2、整体问题的最优解是依赖于子问题的最优解
3、大问题分解成小问题以后,这些小问题之间还有相互重叠的小问题
4、为避免重复求解子问题,我们可以自上而下分析问题,自下而上求解问题
(动态规划的本质就是自下而上求解问题)
最优子结构:
通过求解子问题的最优解,可以获得原问题的最优解
我们在动态规划运用递归时还要注意,其中是否有重叠子问题和最优子结构
在这里插入图片描述
现在添加一个2000美元的手机,背包还是4磅,计算出最优解
基本题目如下:
有4样商品,分别是
(1)音响:4磅:3000美元
(2)笔记本电脑:3磅:2000美元
(3)iphone:1磅:2000 美元
(4)吉他:1磅:1500美元
只有一个4磅的背包,如何使商品价值最大
下面是代码行:

  1. #背包问题
  2. import numpy as np
  3. price=[3000,2000,2000,1500] #价格
  4. weight=[4,3,1,1] #对应的重量
  5. m=4 #背包重量
  6. n=4 #物品数
  7. x=np.zeros([n+1,m+1])
  8. for i in range(1,n+1):
  9. for j in range(1,m+1):
  10. if weight[i-1]<=j:
  11. x[i][j]=max(x[i-1][j],x[i-1][j-weight[i-1]]+price[i-1])
  12. else:
  13. x[i][j]=x[i-1][j]
  14. print(x)
  15. res=x
  16. def show(n,m,w,res):
  17. print('最大价值为:',res[n][m])
  18. item=[False for i in range(n)]
  19. j=m
  20. for i in range(n,0,-1):
  21. if res[i][j]>res[i-1][j]: #代表取了这件物品
  22. item[i]=True
  23. j=j-weight[i]
  24. for i in range(n):
  25. if item[i]:
  26. print('第',i,'个,',end='')
  27. show(n,m,weight,res)

结果:
在这里插入图片描述
例题2:走网格
在这里插入图片描述

  1. import numpy as np
  2. class Robot:
  3. def countWays(self, x, y):
  4. if x == 1 or y == 1:
  5. return 1
  6. else:
  7. dp = np.ones((x,y))
  8. for i in range(1,x):
  9. for j in range(1,y):
  10. dp[i][j]=dp[i][j-1]+dp[i-1][j]
  11. return int(dp[-1][-1])

习题1:减绳子
剑指offer习题14
给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]k[1]…*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18。m是未知的,我么只求分割的总的乘积最大
在这里插入图片描述

  1. class solution:
  2. def __init__(self):
  3. self.res=-1
  4. def Integerbreak(self,n):
  5. return breakInteger(n)
  6. def max3(self,a,b,c):
  7. return (max(a,max(b,c)))
  8. # 将n进行分割,至少分割两部分,可以获得的最大的乘积
  9. def breakInteger(self,n):
  10. if n==1:
  11. return 1
  12. #这里的res是多个值中选取最大值的比较方法,我们比如我们要比较a,b,c,我们可以找一个中介变量
  13. #遍历一遍a,b,c,每次将值和res比较,将较大的值给res,最后遍历完res便是最大值
  14. res=-1
  15. for i in range(1,n):
  16. res=self.max3(res,i*(n-i),i*self.breakInteger(n-i))
  17. return res
  18. print(solution().max3(1,2,3))
  19. print(solution().breakInteger(8))
  20. def max_n(List):
  21. res=-1
  22. for i in List:
  23. res=max(res,i)
  24. return res
  25. print(max_n([1,2,4,3,2,3,4]))

补充习题,求一个数分割的组合数
比如10可以分割成哪几个数的组合,有(1,9),(2,8),(3,2,2,3)等等

  1. class solution1:
  2. def max_spilt(self,n):
  3. self.dic = {
  4. i:None for i in range(1,n+1)}
  5. #print(self.dic)
  6. return self.max_count_mixnum(n)
  7. #将n进行最少分割两次的组合数的集合
  8. def max_count_mixnum(self,n):
  9. a=False
  10. if n==1:
  11. return [[1]]
  12. arr1=[]
  13. for i in range(1,n):
  14. if self.dic[n-i] is not None:
  15. a=True
  16. res=self.dic[n-i]
  17. else:
  18. res=self.max_count_mixnum(n-i)
  19. for j in res:
  20. j.append(i)
  21. arr1.append(j)
  22. if a:
  23. self.dic[n-i]=arr1
  24. return arr1

发表评论

表情:
评论列表 (有 0 条评论,331人围观)

还没有评论,来说两句吧...

相关阅读