NP完全问题 NP-Completeness

原创翻译加学习笔记,方便国人学习算法知识!

原文链接http://www.geeksforgeeks.org/np-completeness-set-1/

我们已经找到很多很高效的算法来解决很难得问题,例如最短路径(shortest path),一笔画问题(Euler graph),最小生成树(minimum spanning tree)等等。这些都是算法设计者的胜利。在这一篇文章中,我们来讨论一下一些失败的例子。

是不是所有的计算问题都可以用计算机解决?

有一切计算问题是没法用算法解决的,即使可以用无限的时间,例如停机问题(给定一个程序P和输入w,程序P在输入w下是否能够最终停止。)艾伦·图灵证明了,不存在解决停机问题的通用算法。这个证明的关键在于对计算机和程序的数学定义。

NP完全问题就是一个失败的例子,没人发现NP完全问题的多项式解法,但是也没人可以证明NP完全问题一定没有多项式解法,有趣的是,如果有人能找到一个NP完全问题的多项式时间解法,那么所有的NP完全问题就都有多项式时间解法。(因为所有的NP 完全问题都可以归约成一个问题)

什么是 P, NP, NP-complete, NP-Hard 问题?

P就是可以在确定型图灵机(deterministic Turing machine)上找到多项式时间解。

NP是一系列决定性问题(decision problem),可以在非确定型图灵机(Non-deterministic Turing Machine)上找到多项式时间解。P问题是NP的子集,也就是说在确定型图灵机上能找到多项式时间解的在非确定型图灵机上同样能找到解。

NP-complete NP完全问题使一些最难的NP 问题,满足以下条件的话,一个问题L就是NP完全问题:

1. L问题是NP问题(给出一个解,可以在多项式时间里来验证(verified)这个解是否正确,但是没法用多项式时间内找到解)

2. 已知的NP-complete问题可以在多项式时间内归约成L问题

如果满足条件2的话,我们就称之为NP-hard问题,但是不需要满足条件1。所以NP-complete 是NP-hard的子集。

下面这个图可以看到P, NP, NP-complete, NP-Hard 之间的关系:

NP完全问题 NP-Completeness

什么是归约?What is Reduction?

假设L1, L2是两个决定性问题(decision problem : 结果只有可能是Yes or No), 算法A2可以解决L2, 如果input Y是L2的输入,运行A2算法时,根据Y的输入是不是和L2相关来给出结果Yes or No。

想法是找到从L1问题到L2问题的转化,这样A2就可以成为A1解法的一部分去解决L1问题。NP完全问题 NP-Completeness

学习如何归约是很重要的。如果我们有一些库函数(library function)去解决一些特定问题,这样我们把新的问题规约到这个已解决的问题,这样可以解决很多时间。例如找最小乘积路径,在一个有向图里路径上权重的最小乘积。如果我们有一个找最短路径的DIjkstra算法的代码,我们可以用log一下所有权重,然后用dijkstra算法找最短路径,这样比重新写一个代码快的多。

怎么样证明一个问题是不是NP-complete?

从NP-complete问题的定义来看,看似很难证明一个问题L是NP-complete。因为根据定义,我们需要证明是否能把所有的NP问题都可以在多项式时间内规约到L。幸运的是我们有另外一条路可以走,就是把一个已知的NP-complete问题规约到L,如果可以在多项式时间内归约,我们就可以证明这个问题L是NP-complete。(如果一个NPC可以归约到L,那么所有的问题都可以在多项式时间内归约到L 有点绕!)

第一个被证明的NP-complete的问题是什么?

一定存在第一个NP-complete通过定义被证明是NP-complete问题。SAT(boolean satisfiablilty problem 布尔可满足性问题)就是第一题个被证明的NP-complete(查看算法导论)

了解NP完全问题对于工程师来说都是很有用的。假设在公司里你被要求写一个高效率的算法来解决一个非常重要的问题。经过了很多思考,你只能想到一个没啥用的指数时间的解法,如果你不知道NP完全,你只能说我想不出一个高效的算法,但当你知道NP完全问题并且能证明这个问题就是NP-complete,你可以很自豪的说基本上不存在多项式时间解。如果存在的话,那么这个解可以解决一个科学教研究了几十年的大问题。

上一篇:小记:web安全测试之——固定session漏洞


下一篇:【01】Nginx:编译安装/动态添加模块