
问题1:从arr数组中选择数字获取最大值,规则是不能选取相邻的数字。比如选择第一个元素arr[0],就无法选择arr[1]。但允许多个选择如选择第1个、第三个、第五个元素。
分析此问题发现又有重叠子问题。
总结出公式:

寻找递归出口:
OPT(1)=arr[0]
OPT(2)=max(arr[0],arr[1])
Python代码:
arr = [1, 2, 4, 1, 7, 8, 3] def rec_opt(arr, i): if i == 0: return arr[0] if i == 1: return max(arr[0], arr[1]) else: A = rec_opt(arr, i - 2) + arr[i] B = rec_opt(arr, i - 1) return max(A, B) print(rec_opt(arr, 6))

此代码虽然正确,但用纯递归写,会产生重叠子问题。
可以写出非递归方法:
import numpy as np arr = [1, 2, 4, 1, 7, 8, 3] # # # def rec_opt(arr, i): # if i == 0: # return arr[0] # if i == 1: # return max(arr[0], arr[1]) # else: # A = rec_opt(arr, i - 2) + arr[i] # B = rec_opt(arr, i - 1) # return max(A, B) def dp_opt(arr): opt = np.zeros(len(arr)) opt[0] = 1 opt[1] = max(arr[1], arr[0]) for i in range(2, len(arr)): A = opt[i - 2] + arr[i] B = opt[i - 1] opt[i] = max(A, B) return opt[len(arr) - 1] # print(rec_opt(arr, 6)) print(dp_opt(arr))
问题2:给定一个数组,从中任意选取元素值(每个元素只能选一次),看能否拼出给定值,如数组arr=[3,34,4,12,5,2],看能否拼出9,10,11,12,13。
arr = [3, 34, 4, 12, 5, 2] def rec_subset(arr, i, s): """arr为待测试数组,i为元素索引,s为目标值""" if s == 0: # 当s为0时,证明之前已经能拼出 return True elif i == 0: # 当只剩一个元素时,只有当此元素等于当前s,才能实现目标 return arr[i] == s else: A = rec_subset(arr, i - 1, s - arr[i]) # 选择当前i元素 B = rec_subset(arr, i - 1, s) # 不选当前i位置元素 return A or B # A/B两种方案任意一种能实现,即可以实现目标 print(rec_subset(arr, 5, 9)) print(rec_subset(arr, 5, 10)) print(rec_subset(arr, 5, 11)) print(rec_subset(arr, 5, 12)) print(rec_subset(arr, 5, 13))
此递归方法同样有重叠子问题。
需要使用一个二维数组tmp来保存bool值。

import numpy as np arr = [3, 34, 4, 12, 5, 2] def dp_subset(arr, s): tmp = np.zeros((len(arr), s + 1), dtype=bool) # 创建保存True or False的二维数组,dtype指定元素类型 tmp[:, 0] = True # 所有行第0列值都为True tmp[0, :] = False # 第0行所有数字等于False tmp[0, arr[0]] = True for i in range(1, len(arr)): # 行 for j in range(1, s + 1): # 列 if arr[i] > s: tmp[i, j] = tmp[i - 1, j] else: A = tmp[i - 1, j - arr[i]] B = tmp[i - 1, j] tmp[i, j] = A or B r, c = tmp.shape #shape函数返回list,array,matrix等的一维和二维长度值。 return tmp[r - 1, c - 1] print(dp_subset(arr, 9)) print(dp_subset(arr, 10)) print(dp_subset(arr, 11)) print(dp_subset(arr, 12)) print(dp_subset(arr, 13))
浙公网安备 33010602011771号