首先应该可以看出这道题是一道典型的树形动态规划。所以,解题的重点应该是怎样构造从子节点到父节点的状态转移方程,而从子节点推出父节点的过程可以通过dfs实现。
对于每个叶子节点,定义编号为0
的节点为它的子节点,则该叶子节点的状态可以由两个编号为0
的节点推出。显然编号为0
的节点不会出错且可能输出0
或1
,所以叶子节点的出错情况只有叶子节点本身损坏时才会发生。所以,如果dp数组只以叶子节点的编号和输出情况为索引,状态转移很难实现。所以我们引入当前节点输出是否正确作为dp数组的第三维,定义dp数组为dp[i][j][k]
,其中i
为当前节点编号,j
为当前节点的输出,k
为当前节点输出是否正确。
初始化:对于编号为
0
的节点,该节点输出必定正确,输出可能为0或1,故初始化为dp[0][1][1] = dp[0][0][1] = 1
。状态表示:如果一个节点的子节点某个状态的dp值为0,说明该子节点不会出现该状态,状态转移时不需要考虑该状态。输入A、B的状态可能情况各有4种,通过长度为4的循环即可枚举出一个输入节点的所有可能状态。对于每个可能状态,注意区分理想情况下和可能出错情况下输入的不同,理想情况下的输出计算时要附加注意考虑输入的正确性,即
!(j ^ k)
;可能出错情况下的输出通过当前节点的输出计算,即k
。状态转移:按照当前状态正确性(即理想输出和可能出错输出是否相等)分类,将子节点的情况数相乘累加,同时考虑取模。
$$
dp[i][j][k] = dp[i][j][k] + (dp[son_A][j_A][k_A] * dp[son_B][j_B][k_B])\qquad k= isEqual(output, realoutput)
$$
代码:
1 |
|