关于 NP 和 NP 完整性的思考方式有很多种。我将从 NP 的定义开始,然后是 NP-hardness,最后是 NP-completeness。
在高层次上,P 和 NP 是一类问题。 P 中的问题是一个是或否的问题(a decision problem),并且有一些算法可以在多项式时间内解决该问题。例如,“你能在这张图中从节点 u 到节点 v 吗?”的问题?属于 P 因为你可以用深度优先搜索来解决它。 (请注意,DFS 本身不在 P 中,因为 DFS 是一个算法,而不是一个问题)。 P 中的另一个问题示例是检查序列是否按排序顺序。
NP 中存在问题,如果它是一个可以验证正确答案的是或否问题(decision problem) em> 在多项式时间内。例如,一个经典的 NP 问题是查看给定一组已知权重的权重,您是否可以选择一组重量正好为某个量 k 的权重(这称为subset sum problem)。确定是否存在具有该属性的一组权重可能很棘手,但如果我给你一组我说我知道是正确的权重,你可以很容易地检查我是否给你正确的一组权重,只需将它们相加并查看它们是否总计为 k。
NP 被称为“非确定多项式”的原因是,对 NP 的另一种思考方式是考虑一种能够以某种方式猜测正确答案的魔法算法多项式时间内的问题。也就是说,如果您可以编写一个允许对问题的答案进行猜测并在多项式时间内运行的算法,那么您正在解决的问题属于 NP。回到我们的权重示例,我们可以为这个问题编写这样一个猜测算法,如下所示。首先,在线性时间内猜测哪一组权重是正确的一组权重,然后将它们全部加起来,看看它们的总和是否为 k。如果是,请报告答案为“是”。否则,说“不”。如果这个程序总是保证做出正确的猜测,那么给定任何有解决方案的问题的输入,它总是会找到一个并报告“是”,如果没有解决方案,它总是会猜错并报告“否”。
目前计算机科学中最基本和最重要的问题之一是,已知存在于 NP 中的任何问题是否也存在于 P 中。也就是说,如果我们可以轻松地验证有效地(在多项式时间内)解决问题的答案,那么我们是否总是可以有效地解决该问题(在多项式时间内)?众所周知,P中的任何问题也是NP中的问题,因为您可以使用多项式时间算法产生答案,然后检查它是否正确,但没有有人曾经找到一种在多项式时间内解决 NP 中的任意问题的方法。
原因是 NP 中的一些问题被称为 NP-complete,这意味着(非正式地)它们至少与NP。如果我们能够有效地解决这些问题(多项式时间),那么我们就可以在多项式时间内解决 NP 中的所有问题。这将是一件大事,因为 NP 中存在许多极其重要的问题,而我们目前还没有好的、快速的算法可以解决这些问题。这也是P = NP question 的魅力所在,因为只需要一种算法就可以证明大量被认为难以解决的问题实际上可以有效地解决。
更正式地说,NP 中的问题称为 NP-完全如果在多项式时间内,您可以转换任何其他 NP 的任何实例> 问题转化为该问题的一个实例。上面的权重问题就是这样一个问题,确定whether a boolean formula has a satisfying assignment,解决整数上的某些优化问题(integer programming),确定访问一组位置的最快路线(traveling salesman),或者确定如何使用最少的频率(graph coloring)在城市中分配蜂窝塔。即使确定是否有可能解决像Sudoku 和minesweeper 这样的游戏,对于任意棋盘大小都是NP-完成的。
(有些问题具有后一种性质 - NP 中的任何问题都可以有效地转换为该问题 - 但它们本身并不属于 NP。这些问题被称为NP-很难。)
从实际的角度来看,如果您曾被要求解决已知为 NP-complete 或 NP-hard 的问题,请不要期望找到在任何合理的时间内得到精确的解决方案。在某些情况下,甚至不可能在任何精度内有效地近似解。你最好寻找一个替代问题来尝试解决,或者让自己接受一个在大多数但不是所有情况下都表现良好的启发式解决方案。
至于你最初认为 DFS 是 NP-complete 的,只有 problems 可以是 NP 或 NP强>-完成;算法不能。 DFS 是一种解决图可达性问题的算法——给定图中的两个节点,是否有从第一个节点到第二个节点的路径?这个问题在 NP 中,因为如果有一条路径很容易检查,但它(可能)不是 NP 完整的,因为我们知道我们可以在多项式时间内使用DFS。
希望这会有所帮助!