打家劫舍问题
"""
打家劫舍问题是一种典型的动态规划问题,按照房间的不同分布,其解法略有轻微的修改,下面分布以三个例子进行介绍
1)房子在一字排开,首尾不相连
2)房子成环形,首尾相连
3)房子成树状结构
"""
"""
1)房子在一字排开,首尾不相连
示例:
输入:[1,2,3,1] output = 4
输入:[2,7,9,3,1] output =12
"""
def rob_on_recursion(input_list):
total_size = len(input_list)
def dp(index):
if index >= total_size:
return 0
res = max(dp(index + 1), input_list[index] + dp(index + 2))
return res
return dp(0)
def house_robber_I(input_list):
dp = [0 for _ in range(len(input_list) + 2)] #状态转移矩阵
for i in range(len(input_list)-1, -1, -1):
dp[i] = max(input_list[i] + dp[i+2], dp[i + 1]) #状态转移公式,从后向前遍历
return dp[0]
#状态压缩,优化空间复杂度
def house_robber_I_1(input_list):
dp_i_2 = 0
dp_i_1 = 0
dp_i = 0
for i in range(len(input_list)-1, -1, -1):
dp_i = max(input_list[i] + dp_i_2, dp_i_1)
dp_i_2 = dp_i_1
dp_i_1 = dp_i
return dp_i
"""
2)房子成环形,首尾相连
"""
def house_robber_II(input_list):
size = len(input_list)
res = max(
rob(input_list, 0, size - 2), #选择第一间房子,放弃最后一间房子
rob(input_list, 1, size - 1) #选择最后一间房子,放弃选择第一间房子
)
return res
def rob(input_list, start, end):
dp_i_2 = 0
dp_i_1 = 0
dp_i = 0
for i in range(end, start-1, -1):
dp_i = max(input_list[i] + dp_i_2, dp_i_1)
dp_i_2 = dp_i_1
dp_i_1 = dp_i
return dp_i
"""
3)房子成树状结构
"""
class TreeNode(object):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def house_robber_III(root):
if root is None:
return 0
do_it = (root.val
+
(0 if root.left is None else house_robber_III(root.left.left) + house_robber_III(root.left.right))
+
(0 if root.right is None else house_robber_III(root.right.left) + house_robber_III(root.right.right))
)
not_do_it = house_robber_III(root.left) + house_robber_III(root.right)
return max(do_it, not_do_it)
if __name__ == "__main__":
input = [2,7,9,3,1]
output = house_robber_I_1(input)
print(output)
posted on 2021-12-16 09:47 random_boy 阅读(93) 评论(0) 收藏 举报
浙公网安备 33010602011771号