我假设给定的输入只能出现在一个叶子中(否则问题再次变成boolean satisfiability--尽管树结构和受限的运算符--根据德摩根定律)。
我相信答案可以在没有数据结构的情况下计算出来。毕竟,您不需要列举解决方案。我认为递归步骤有两个参数:要处理的节点,以及该节点要产生的目标输出,它返回两个值:实现节点目标的方法数,以及下面的叶子总数节点。这两个都可以通过对树的单个深度优先遍历来获得。
下面是这个想法的伪代码:
(int ways, int leaves) = recurse(Node n, bool target) {
//Base case of recursion:
if(n.type == LEAF) {
return (1, 1);
}
else if(n.type == NOT) {
//for a NOT, we just invert the target.
return recurse(n.child[0], !target)
}
else if (n.type == AND) {
//AND is more complicated. First, count the ways that we can make each
//sub-expression evaluate to true, and the total number of leaves under
//both the left and right child:
(int left_true, int left_leaves) = recurse(n.child[0], true);
(int right_true, int right_leaves) = recurse(n.child[1], true);
//the total number of ways to make a true AND result is the product of
//the number of ways to make the left true, and the number of ways to
//make the right true.
int total_true_ways = left_true * right_true;
//the total number of leaves under this node is the sum of leaves under
//the left and right subtrees.
int total_leaves = left_leaves + right_leaves;
if(target == true) {
//if this node's target is 'true' we've already computed the number of
//ways to satisfy that.
return (total_true_ways, total_leaves);
}
else {
//The number of ways to make a 'false' is the total number of possible
//input combinations, less the number of input combinations that make
//a 'true'.
//The total number of possible input combinations is given by 2 to the
//power of the number of boolean inputs, which is given by the
//number of leaves below the node:
int num_possible_inputs = pow(2, total_leaves);
return ( num_possible_inputs - total_true_ways, total_leaves);
}
}
else {
throw internal error
}
}
不幸的是,运行时间不能严格地用叶子的数量表示,因为您的树不排除任意长的 NOT 操作链。如果我们假设没有背靠背的 NOT 分支,那么最大深度的树是通过交替的 NOT 和 AND 层来实现的,从而得到具有2*ciel(log_2(n)+1) 层和2n + 2(n-1) 总节点的树。 (其中n 是叶节点的数量。)因此,在假设没有背靠背NOT 运算符的情况下,一次触及每个节点的深度优先遍历在O(n) 中运行。