执行结果:通过
执行用时和内存消耗如下:
int dfs(int node, int parent, int f, int* coins, int k, int **children, int *childCount, int **memo) {
if (memo[node][f] != -1) {
return memo[node][f];
}
int res0 = (coins[node] >> f) - k;
int res1 = coins[node] >> (f + 1);
for (int i = 0; i < childCount[node]; ++i) {
int child = children[node][i];
if (child == parent) {
continue;
}
res0 += dfs(child, node, f, coins, k, children, childCount, memo);
if (f + 1 < 14) {
res1 += dfs(child, node, f + 1, coins, k, children, childCount, memo);
}
}
return memo[node][f] = fmax(res0, res1);
}
int maximumPoints(int **edges, int edgesSize, int *edgesColSize, int *coins, int coinsSize, int k) {
int* childCount = (int*)malloc(coinsSize * sizeof(int));
memset(childCount, 0, coinsSize * sizeof(int));
for (int i = 0; i < edgesSize; ++i) {
int u = edges[i][0];
int v = edges[i][1];
childCount[u]++;
childCount[v]++;
}
int** children = (int**)malloc(coinsSize * sizeof(int*));
for (int i = 0; i < coinsSize; ++i) {
children[i] = (int*)malloc(childCount[i] * sizeof(int));
}
memset(childCount, 0, coinsSize * sizeof(int));
for (int i = 0; i < edgesSize; ++i) {
int u = edges[i][0];
int v = edges[i][1];
children[u][childCount[u]++] = v;
children[v][childCount[v]++] = u;
}
int **memo = (int **)malloc(coinsSize * sizeof(int *));
for (int i = 0; i < coinsSize; i++) {
memo[i] = (int *)malloc(14 * sizeof(int));
memset(memo[i], -1, 14 * sizeof(int));
}
int result = dfs(0, -1, 0, coins, k, children, childCount, memo);
for (int i = 0; i < coinsSize; ++i) {
free(children[i]);
free(memo[i]);
}
free(children);
free(memo);
free(childCount);
return result;
}
解题思路:
这段代码实现了一个深度优先搜索(DFS)算法,用于解决一个特定的问题,该问题涉及到一个树状结构,每个节点都拥有一定数量的"硬币"(由coins
数组表示),并且有一个特定的参数k
。目标是在满足某些条件下,最大化能够收集到的硬币数量。以下是对代码思路的详细解释:
函数 dfs
- 参数解释 :
node
:当前正在访问的节点。parent
:当前节点的父节点,用于避免向上回溯时重复访问父节点,形成环路。f
:当前考虑的位(bit),用于在coins
数组中按位选择硬币数量。coins
:一个整数数组,每个元素表示对应节点的硬币数量,通过位操作来访问不同范围内的硬币数量。k
:一个阈值,用于与按位操作后的硬币数量进行比较。children
:一个二维数组,存储每个节点的子节点列表。childCount
:一个整数数组,存储每个节点的子节点数量。memo
:一个二维数组,用于记忆化搜索,避免重复计算。
- 逻辑 :
- 记忆化检查 :首先检查
memo[node][f]
是否已经被计算过,如果是,则直接返回结果。 - 计算当前节点的贡献 :
res0
:当前节点在不考虑更高位的情况下,能够贡献的硬币数量(与k
比较后)。res1
:当前节点在考虑更高位的情况下,能够贡献的硬币数量。
- 递归遍历子节点 :
- 对于每个子节点,递归调用
dfs
函数,更新res0
和res1
。 - 注意,当考虑更高位时(
f + 1
),只有f + 1 < 14
时才进行递归,这可能是因为coins
数组中的数值最多只有14位有效(或出于其他特定限制)。
- 对于每个子节点,递归调用
- 返回结果 :返回
fmax(res0, res1)
,即两种情况下的最大值,并更新memo[node][f]
。
- 记忆化检查 :首先检查
函数 maximumPoints
- 参数解释 :
edges
:一个二维数组,表示树的边,edges[i] = [u, v]
表示节点u
和节点v
之间有一条边。edgesSize
:edges
数组的大小。edgesColSize
:edges
数组中每个子数组的大小(这里似乎未直接使用,但通常用于表示二维数组的第二维大小)。coins
:一个整数数组,表示每个节点的硬币数量。coinsSize
:coins
数组的大小,也即节点的数量。k
:与dfs
函数中的k
相同,用于比较硬币数量。
- 逻辑 :
- 初始化 :为
childCount
、children
和memo
数组分配内存,并初始化。 - 构建树的表示 :通过遍历
edges
数组,构建每个节点的子节点列表和子节点数量。 - 记忆化搜索 :调用
dfs
函数,从根节点(假设为0)开始搜索,parent
参数设为-1表示根节点没有父节点。 - 释放内存:释放之前分配的内存,避免内存泄漏。
- 返回结果 :返回
dfs
函数的结果,即从根节点开始能够收集到的最大硬币数量。
- 初始化 :为
总结
这段代码通过深度优先搜索(DFS)和记忆化搜索,在给定一个树状结构和每个节点的硬币数量的情况下,计算并返回在满足特定条件(与k
比较)下能够收集到的最大硬币数量。通过位操作和递归,高效地遍历树并计算每个节点的贡献。