题一:给定数组arr,求出arr中不相邻节点之和最大值
输入:arr = [1,2,4,1,7,8,3]
输出:15
解题思路:
o
p
t
(
0
)
=
a
r
r
[
0
]
opt(0) = arr[0]
opt(0)=arr[0]
o
p
t
(
1
)
=
m
a
x
{
a
r
r
[
0
]
a
r
r
[
1
]
opt(1)=max \begin{cases} arr[0]\\ arr[1] \end{cases}
opt(1)=max{arr[0]arr[1]
o p t ( i ) = m a x { 选 : o p t ( i − 2 ) + a r r [ i ] 不 选 o p t ( i − 1 ) opt(i)=max \begin{cases} 选:opt(i-2) + arr[i]\\ 不选opt(i-1) \end{cases} opt(i)=max{选:opt(i−2)+arr[i]不选opt(i−1)
#动态规划,本题求出arr中不相邻节点之和最大值
#解题思路:
arr = [1,2,4,1,7,8,3]
#方法一:递归
def rec_opt(arr,i):
if i == 0:
return arr[0]
elif 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
def dp_opt(arr):
opt = np.zeros(len(arr))
#下标0最优解就是arr[0]
#下标1最优解是max(arr[0], arr[1])
opt[0] = arr[0]
opt[1] = max(arr[0], arr[1])
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(dp_opt([4,1,1,9,1]))
题二:判断一个数,能否由列表中的数组成
递归出口
if s == 0: return True #space为0的时候,不放也满了
if i == 0: return arr[0] == s #当只剩一个数,只需判断与剩余空间s的大小
if arr[i] > s:
return subset(arr,i-1,s)
o
p
t
(
i
)
=
m
a
x
{
选
:
s
u
b
s
e
t
(
a
r
r
,
i
−
1
,
s
−
a
r
r
[
i
]
)
不
选
:
s
u
b
s
e
t
(
a
r
r
,
i
−
1
,
s
)
opt(i)=max \begin{cases} 选:subset(arr, i-1, s-arr[i]) \\ 不选:subset(arr, i-1, s) \end{cases}
opt(i)=max{选:subset(arr,i−1,s−arr[i])不选:subset(arr,i−1,s)
方法一:递归
#递归出口
# if s == 0: return True
# if i == 0: return arr[0] == s
# if arr[i] > s:
# return subset(arr,i-1,s)
arr = [3, 34, 4, 12, 5, 2]
def rec_subset(arr, i, s):
if s == 0:
return True
elif i == 0:
return arr[0] == s
elif arr[i] > s:
return rec_subset(arr,i-1,s)
else:
#选
A = rec_subset(arr, i-1, s-arr[i])
#不选
B = rec_subset(arr, i - 1, s)
return A or B
print(rec_subset(arr, len(arr)-1, 9))
方法二:非递归
import numpy as np
def dp_subset(arr, S):
subset = np.zeros((len(arr), S+1), dtype=bool)
subset[:, 0] = True # 0代表空间已经装满,所以赋值为 True
subset[0, :] = False # 初始化箱子,空间没装值
if arr[0] <= S:
subset[0, arr[0]] = True # 放入arr[0],这个地方肯定满足
for i in range(1, len(arr)):
for s in range(1, S+1):
if arr[i]>s:
subset[i, s] = subset[i-1, s]
else:
A = subset[i-1, s-arr[i]] #dp[i][j]目的就是求当前i,j的状态
B = subset[i-1, s] #不选就是看前面那个字符,而且字符是累积状态
subset[i, s] = A or B
r, c = subset.shape
return subset[r-1, c-1]
print(dp_subset(arr, 9))