![]() |
1
1
20!相当大,大于2^61。幸运的是,有更好的方法来解决小实例:(编辑)动态编程。通过保存每个子问题的最优解,我们需要花费一些内存来获得非常大的时间节省。 下面是一些用Python编写的示例代码。在用另一种语言实现下面的代码时,您可能需要对顶点0,…,n-1进行编号,并将这些集合实现为位向量。
这个问题的NP硬度从设定覆盖降低。
保持客观价值
. 这意味着,除非p=np,否则多项式时间算法的最佳保证就是它总是输出一个最多为
如果
(注意,对于集合覆盖,贪婪算法达到最佳近似比!对于您的问题,类似的情况可能是正确的。) |
![]() |
2
2
我会用不同的方式来描述这个问题。要将顶点分成两组。第一组由“根节点”和第二组“从属节点”组成,即直接连接到根节点的节点。 root dependent B A < C E D < F 图0:可能的结果图。 您希望最小化根节点的数量。这与最大化依赖节点的数量相同,这与最大化结果图中的边数相同,这与最小化从开始图构建时移除的边数相同。 让我们先看看蛮力:对于将节点分成一个根集和一个从属集的每个二部分,首先检查它是否满足问题语句的条件,最后尽可能做到最好。有一个指数数量的两分法,所以这将必须加以完善。 如果我们将每个边视为具有可能的状态“未知”、“取下”或“移除”,取下一个边将移除源自其末端节点的所有边以及结束于该节点的所有边(见图1)。但是,无论如何,我们最多可以保留一个以特定节点结尾的边。 A B C \|/ D /|\ E F G 图1:取A-D边,删除此处显示的所有其他边。 有许多“贪婪”的启发式方法:
这就存在这样一个问题,即一些连接的节点将更好地放入根集,这将使我们得到第一次优化:
这看起来很好,但不一定是最佳的。也许你可以从另一边开始:
我仍然不能证明这是否是最佳的,但至少我不能直接想到一个打破它的情况。 |
![]() |
danial · 如何在多个字符串的每个位置找到最频繁的字符 2 年前 |
![]() |
Manny · 如何比较Perl中的字符串? 2 年前 |
![]() |
Diret · 获取范围内每个数字的子倍数的算法 2 年前 |
![]() |
Saif · 排序时python如何决定何时调用比较器? 2 年前 |