1. import numpy as np
    2. from functools import wraps
    3. """假设有几种硬币,如1、3、5,并且数量无限。请找出能够组成某个数目的找零所使用最少的硬币数。
    4. 解法:
    5.   用待找零的数值k描述子结构/状态,记作sum[k],其值为所需的最小硬币数。对于不同的硬币面值coin[0...n]
    6. ,有sum[k] = min(sum[k-coin[0]] , sum[k-coin[1]], ...)+1。对应于给定数目的找零total,需要求解sum[total]的值"""
    7. """1.直接自顶向下实现递归式,并将中间结果保存,这叫备忘录法;"""
    8. """带备忘录的递归方式的优点就是易于理解,易于实现,代码简洁干净,运行速度也不错,直接从需要求解的问题出发,
    9. 而且只计算需要求解的子问题,没有多余的计算。但是,它也有自己的缺点,因为是递归形式,所以有限的栈深度是它的硬伤,有些问题难免会出现栈溢出了。"""
    10. from functools import wraps
    11. def memo(func):
    12. cache = {}
    13. @wraps(func)
    14. def wrap(*args):
    15. if args not in cache:
    16. cache[args] = func(*args)
    17. return cache[args]
    18. return wrap
    19. @memo
    20. def ccc(total):
    21. list1 = []
    22. if total in [1, 3, 5]:
    23. return 1
    24. if total > 1:
    25. list1.append(ccc(total-1))
    26. if total > 3:
    27. list1.append(ccc(total-3))
    28. if total > 5:
    29. list1.append(ccc(total-5))
    30. su = min(list1) + 1
    31. return su
    32. from functools import wraps
    33. def memo(func):
    34. cache = {}
    35. @wraps(func)
    36. def wrap(*args):
    37. if args[1] not in cache:
    38. cache[args[1]] = func(*args)
    39. return cache[args[1]]
    40. return wrap
    41. @memo
    42. def ca(p, total):
    43. li = []
    44. if total in p:
    45. return 1
    46. else:
    47. for i in p:
    48. if total >= i:
    49. li.append(ca(p, total-i))
    50. s = min(li) + 1
    51. return s
    52. from functools import wraps
    53. def memo(func):
    54. cache = {}
    55. @wraps(func)
    56. def wrap(*args):
    57. if args[1] not in cache:
    58. cache[args[1]] = func(*args)
    59. return cache[args[1]]
    60. return wrap
    61. @memo
    62. def ca(p, total):
    63. mi = total
    64. if total in p:
    65. return 1
    66. for i in p:
    67. if total >= i:
    68. count = ca(p, total-i) + 1
    69. if count < mi:
    70. mi = count
    71. return mi
    72. """2.按照递归式自底向上地迭代,将结果保存在某个数据结构中求解
    73. """
    74. """于是,迭代版本的实现方式就诞生了!
    75. 迭代实现方式有2个好处:1.运行速度快,因为没有用栈去实现,也避免了栈溢出的情况;2.迭代实现的话可以不使用dict来进行缓存,
    76. 而是使用其他的特殊cache结构,例如多维数组等更为高效的数据结构。"""
    77. def bbb(p, v):
    78. n1 = len(p) + 1
    79. n2 = v + 1
    80. s = np.array([[0] * n2] * n1)
    81. for i in range(1, n1):
    82. for j in range(min(p), n2):
    83. list1 = []
    84. for x in p:
    85. if j > x and j - x >= min(p):
    86. list1.append(s[i, j - x])
    87. elif j == x:
    88. list1.append(0)
    89. s[i, j] = min(list1) + 1
    90. return s
    91. import numpy as np
    92. if __name__ == '__main__':
    93. p = [1, 3, 5]
    94. v = 10
    95. s = bbb(p, v)
    96. print(s)
    97. import copy
    98. def ca(p, v):
    99. n1 = len(p)
    100. s = np.array([[0] * n1] * v)
    101. l1 = {}
    102. for i in range(v):
    103. min_count = v
    104. l1[i] = []
    105. for j in range(n1):
    106. if i == p[j]:
    107. min_count = 1
    108. l1[i] = []
    109. l1[i].append(p[j])
    110. if i > p[j] and s[i-p[j], j] + 1 < min_count:
    111. min_count = s[i-p[j], j] + 1
    112. l1[i] = copy.copy(l1[i-p[j]])
    113. l1[i].append(p[j])
    114. s[i, j] = min_count
    115. return s, l1
    116. Min=[x for x in range(12)];
    117. VN=[2,3,5];
    118. for i in range(1,12,1):
    119. for j in range(3):
    120. if VN[j]<=i and Min[i-VN[j]]+1<Min[i]:
    121. Min[i]=Min[i-VN[j]]+1;
    122. print(Min[1::1])
    123. """这就是递归实现和迭代实现的重要区别:递归实现不需要去考虑计算顺序,只要给出问题,然后自顶向下去解就行;
    124. 而迭代实现需要考虑计算顺序,并且顺序很重要,算法在运行的过程中要保证当前要计算的问题中的子问题的解已经是求解好了的。"""
    125. """如果当前物品大于背包的容积,这个物品太大了,包塞不下。那么最优解就是前n-1件物品放进这个背包的最大价值。
    126. arr[i][j] = arr[i-1][j]
    127. 如果当前物品不大于背包的容积,这个物品可以塞下,需要重新开始计算,当前 i 物品组合的最大价值。分为两种情况,该物品放还是不放。
    128. 2.1 不放的话,和上面的公式相同;
    129. 2.2 放的话,则背包容量减去第n件物品的重量,再去装前 i-1 件物品,所得的最大价值。两种情况中较大的就是最优解。
    130. arr[i][j] = max (arr[i-1][j] , arr[i-1][j -v[i]]+ cost[j])
    131. 一般来说,只要问题可以划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解(即满足最优子化原理),则可以考虑用动态规划解决。
    132. 动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。
    133. """
    134. """m个物品价值为 p[m],体积为 w[m],现有一个容量为 v 的背包,怎么装物品价值最大?"""
    135. def kkk(p, w, v):
    136. n1 = len(p) + 1
    137. n2 = v + 1
    138. s = np.array([[0] * n2] * n1)
    139. # for x in range(n2):
    140. # s[0, x] = x
    141. for i in range(1, n1):
    142. # s[i, 0] = p[i-1]
    143. for j in range(1, n2):
    144. if p[i-1] > j:
    145. s[i, j] = s[i-1, j]
    146. else:
    147. s[i, j] = max(s[i-1, j], s[i-1, j-p[i-1]] + w[i-1])
    148. return s
    149. p = [3, 2, 9, 4, 3]
    150. w = [700, 500, 800, 600, 520]
    151. v = 8
    152. c = kkk(p, w, v)
    153. import copy
    154. length = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    155. profit = (1, 5, 8, 9,10, 17, 17, 20, 24, 30)
    156. n = 20
    157. def ddd(length, profit, n):
    158. dic = {}
    159. dic[0] = []
    160. s = [0] * (n)
    161. for i in range(1, n):
    162. ma = -1
    163. for j in range(len(length)):
    164. y = s[i-length[j]] + profit[j]
    165. if i >= length[j] and y > ma:
    166. ma = y
    167. dic[i] = []
    168. dic[i] = copy.deepcopy(dic[i-length[j]])
    169. dic[i].append(length[j])
    170. s[i] = ma
    171. return s, dic
    1. // 扔鸡蛋问题 解析
    2. func main(){
    3. floors := 100
    4. eggs := 2
    5. dp := [3][101]int {}
    6. // 外面这两层循环(循环鸡蛋数量和楼层数量)是为了将dp二维数组的每一个值遍历到
    7. for egg:=1; egg < eggs+1; egg++ {
    8. for floor:=1; floor < floors + 1; floor++ {
    9. // 解决这样的干扰非常有必要,把底层边界进行固定,最大程度防止 0, 1的错误
    10. // 这步判断是解决掉 最初状态的干扰,鸡蛋只有一个
    11. if egg == 1{
    12. dp[1][floor] = floor
    13. continue
    14. }
    15. // 这两部判断是解决掉 最初状态的干扰,只有一层楼的状态
    16. if floor == 1{
    17. dp[egg][1] = 1
    18. continue
    19. }
    20. tmpMin := floors
    21. // 这一层遍历是进行状态转移核心,限定了当前的 egg和floor时
    22. // 通过遍历当前floor 之前的已知解,从中取出最优方案
    23. for sonFloor:=1; sonFloor < floor; sonFloor++ {
    24. tmpMax := 0
    25. // dp[egg][floor-sonFloor] 鸡蛋没碎,考虑剩下几层楼所需要的最优解
    26. //
    27. if dp[egg][floor-sonFloor] <= dp[egg-1][sonFloor-1] {
    28. tmpMax = dp[egg-1][sonFloor-1] + 1
    29. } else {
    30. tmpMax = dp[egg][floor-sonFloor] + 1
    31. }
    32. if tmpMax < tmpMin {
    33. tmpMin = tmpMax
    34. }
    35. }
    36. dp[egg][floor] = tmpMin
    37. }
    38. }
    39. fmt.Println(dp)
    40. fmt.Println(dp[eggs][floors])
    41. }