过去通过网站上的快速搜索,已经有很多关于这个主题的帖子,其中许多都使用了这种动态编程重复:
C(x) = min(1 + sum (C(i) for i in x's children), len(x's children) + sum(C(i) for i in x's sunchildren))
假设树以节点 1 为根,我对节点链 1-2-3-4-5-6 尝试了此算法,以获得以下 C(i):
| C(1) | C(2) | C(3) | C(4) | C(5) | C(6) |
| 3 | 2 | 2 | 1 | 1 | 1 |
但是,C(1) 的正确答案应该是 2,这是通过标记节点 2 和 5 来实现的。
我决定尝试我自己的方法,详情如下:
int solve(int curr, int height){
if(dp[curr][height] > -1) return dp[curr][height];
if(int(children[curr].size()) == 0) return dp[curr][height] = height > 1 ? 1 : 0;
if(height == 3){
int ret = 1;
for(int i = 0; i < int(children[curr].size()); i++){
int next = children[curr][i];
ret += solve(next, 1);
}
return dp[curr][height] = ret;
}
int ret1 = 0; int ret2 = 1;
if(height == 2){
for(int i = 0; i < int(children[curr].size()); i++){
int next = children[curr][i];
ret1 += solve(next, 3); ret2 += solve(next, 1);
}
return dp[curr][height] = min(ret1, ret2);
}
for(int i = 0; i < int(children[curr].size()); i++){
int next = children[curr][i];
ret1 += solve(next, 2); ret2 += solve(next, 1);
}
return dp[curr][height] = min(ret1, ret2);
}
curr是我们所在的当前节点,height是距其上方最近的标记节点的距离。这个想法是,一旦节点的高度 = 3,就必须在该特定路径中标记它。否则,我们现在可以跳过标记它。一个例外是叶子节点,如果没有标记相邻节点,则必须标记它。
有人可以验证我的方法的有效性,并解释为什么第一个算法未能通过链测试吗?
提前致谢!