打家劫舍问题

"""
打家劫舍问题是一种典型的动态规划问题,按照房间的不同分布,其解法略有轻微的修改,下面分布以三个例子进行介绍
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)    收藏  举报

导航