小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。 除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。 给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。 用C++实现
时间: 2024-01-24 08:20:21 浏览: 24
题目描述中没有给出每个节点的价值,假设每个节点都有一个价值 val。那么这就是一道典型的二叉树动态规划问题。
我们可以定义一个函数 rob(root) 来表示盗取以 root 为根的二叉树的最大价值。对于每个节点来说,有两种情况:
1. 如果盗取这个节点,那么它的左右子节点就不能盗取,因此最大价值就是 root->val + rob(root->left->left) + rob(root->left->right) + rob(root->right->left) + rob(root->right->right)。
2. 如果不盗取这个节点,那么左右子节点可以任意选择是否盗取,因此最大价值就是 rob(root->left) + rob(root->right)。
综上所述,我们可以得到以下递归式:
rob(root) = max(root->val + rob(root->left->left) + rob(root->left->right) + rob(root->right->left) + rob(root->right->right), rob(root->left) + rob(root->right))
最后需要注意的是,我们需要对每个节点进行重复计算,因此可以使用记忆化搜索来优化时间复杂度。
下面是C++代码实现:
相关问题
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。 除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。 给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。要求:C++,输入root数组,其中包括空节点null,输出最高金额
这是一道经典的树形动态规划问题,可以使用递归解决。对于每个节点,我们可以选择偷或不偷,偷了就要加上该节点的值,不偷就不用加。如果选择偷该节点,则不能偷其子节点;如果选择不偷该节点,则可以选择偷其子节点或不偷。因此,对于每个节点,我们可以得到以下状态转移方程:
偷该节点:dp[node][1] = node->val + dp[node->left][0] + dp[node->right][0]
不偷该节点:dp[node][0] = max(dp[node->left][0], dp[node->left][1]) + max(dp[node->right][0], dp[node->right][1])
最终的答案即为根节点的两种状态中的较大值,即 max(dp[root][0], dp[root][1])。以下是 C++ 的代码实现:
```c++
int rob(TreeNode* root) {
unordered_map<TreeNode*, int> dp; // 记忆化搜索
return dfs(root, dp);
}
int dfs(TreeNode* node, unordered_map<TreeNode*, int>& dp) {
if (!node) return 0;
if (dp.count(node)) return dp[node]; // 如果已经计算过,则直接返回
int rob_node = node->val + (node->left ? dfs(node->left->left, dp) + dfs(node->left->right, dp) : 0)
+ (node->right ? dfs(node->right->left, dp) + dfs(node->right->right, dp) : 0);
int not_rob_node = dfs(node->left, dp) + dfs(node->right, dp);
dp[node] = max(rob_node, not_rob_node);
return dp[node];
}
```
用最短路径算法写一个追踪游戏
好的,我可以给你一个基于 Dijkstra 算法的追踪游戏实现。这个游戏的规则是,有一个警察和一个小偷,在一个城市里行动。警察要尽快地抓住小偷,小偷要尽可能地逃脱。每个街区都有一个固定的警察和小偷的位置。
这个游戏的实现可以分为以下几个步骤:
1.定义一个地图,包括街区的位置和道路的连接情况。
2.定义警察和小偷的初始位置。
3.使用 Dijkstra 算法计算从警察到小偷的最短路径。
4.警察按照最短路径移动,小偷则根据一定的策略移动。
5.重复步骤 3 和 4,直到小偷被捕或者逃脱成功。
下面是这个游戏的 Python 实现代码:
```python
import heapq
class Graph:
def __init__(self):
self.vertices = {}
def add_vertex(self, name, edges):
self.vertices[name] = edges
def shortest_path(self, start, end):
heap = [(0, start)]
visited = set()
while heap:
(cost, current) = heapq.heappop(heap)
if current in visited:
continue
visited.add(current)
if current == end:
return cost
for (neighbor, next_cost) in self.vertices[current].items():
heapq.heappush(heap, (cost + next_cost, neighbor))
return -1
class Police:
def __init__(self, graph, start):
self.graph = graph
self.location = start
def move(self, target):
path = self.graph.shortest_path(self.location, target)
if path != -1:
self.location = target
class Thief:
def __init__(self, graph, start):
self.graph = graph
self.location = start
def move(self, police):
min_distance = float('inf')
best_location = self.location
for neighbor in self.graph.vertices[self.location]:
distance = self.graph.shortest_path(neighbor, police.location)
if distance < min_distance:
min_distance = distance
best_location = neighbor
self.location = best_location
if __name__ == '__main__':
g = Graph()
g.add_vertex('A', {'B': 5, 'C': 2})
g.add_vertex('B', {'D': 4})
g.add_vertex('C', {'D': 2, 'E': 3})
g.add_vertex('D', {'F': 1})
g.add_vertex('E', {'F': 7})
g.add_vertex('F', {})
police = Police(g, 'A')
thief = Thief(g, 'F')
while True:
police.move(thief.location)
thief.move(police)
print(f'Police: {police.location}, Thief: {thief.location}')
if police.location == thief.location:
print('Thief is caught!')
break
```
这个实现中,我们首先定义了一个 `Graph` 类,用于表示地图和计算最短路径。然后,我们定义了一个 `Police` 类和一个 `Thief` 类,分别表示警察和小偷。在每个回合中,警察会按照最短路径移动,小偷则会选择离警察最远的位置移动。如果警察和小偷在同一个位置,游戏结束。
上面的代码只是一个简单的示例,你可以根据自己的需求更改地图和初始位置,以及警察和小偷的移动策略。