算法导论之P、NP、NPC问题

P、NP、NPC


概念

> P问题:能够在多项式时间内解决的决策问题。

—举例: 图搜索问题、最短路径问题、最小生成树问题······


> NP问题:不能在多项式时间内解决或不确定能不能在多项式时间内解决,但能在多项式时间验证的问题。

—验证:给定一个问题的实例、证书(类似于证据),需要验证这个证书是这个问题的正确答案。

— 举例:汉密尔顿路径,实例为G=(V,E),证书为顶点序列 {v0,v1,v2,v3,….,vk},我们的目的是要验证这个证书就是这个问题的答案,验证方法为:先遍历一遍这个点序列,看看是不是每个点只出现一次,然后对于(vi,vi+1)是否为G的边,这样就能够验证这个点序列是不是汉密尔顿路径,很显然这个验证过程是多项式时间的,所以汉密尔顿路径是NP问题。


> NPC问题:目前不能用多项式时间解决的问题,但是我们还不能证明这个问题不能用多项式时间解决,我们这次的目标是研究这个问题。

—满足的两个条件:是一个NP问题 + 所有的NP问题可以在多项式时间内规约到它

—举例:3SAT、顶点覆盖、团、三维匹配、汉密尔顿回路、划分问题·······


> NP难问题:所有的NP问题可以在多项式时间归约到它,但它不一定是一个NP问题


> 归约(约化)的标准概念: 如果能找到这样一个变化法则,对程序A的任意一个输入,都能按这个法则变换成程序B的输入,使这两个程序的输出相同,那么我们说,问题A可归约为问题B

— 问题A可以约化到问题B的含义是,可以用解决B的解法来解决A,或者说A可以“变成”B。

—A可归约为B的直观含义:B的时间复杂度>=A的时间复杂度。也即,A比B简单。


关系

P、NP、NPC、NP Hard问题的关系如下:


证明NPC问题

证明问题B是NPC问题的过程如下:

  1. 证明B是NP问题
  2. 知道一个已知的NPC问题A
  3. 证明A归约到B。

常见归约问题

基本知识

1、独立集 —— 在图G = (VE)中,如果顶点集合S?V中的任意两点之间都没有边,则称S是独立的。

—难点: 寻找最大独立集。

—目标: 装入尽可能多的顶点,要求边涉及到的边服从一些限制条件。


2、顶点覆盖 —— 给定图G = (VE),顶点集合S?V,如果图中的每一条边至少有一个端点在S中,则称S是一个顶点覆盖。

—难点: 寻找最小顶点覆盖。

—目标: 用尽可能少的顶点覆盖图中的所有边。


3、集合覆盖 —— 试图用一组较小的集合覆盖一个任意的对象集合。


常见问题

1、独立集问题——给定图G和数k,问是否包含大小至少为k的独立集?


2、顶点覆盖问题——给定图G和数k,问G是否包含大小至多为k的顶点覆盖?


3、集合覆盖问题——给定n个元素的集合U,U的子集S1,···,Sm以及数k,问在这些子集中有一组子集,它们的并等于整个U且至多包含k个子集吗?


4、集合包装问题——给定n个元素的集合U,U的子集S1,····,Sm以及数k,问在这些子集中至少有k个两两不相交吗?


5、SAT(可满足性问题)——给定bool变量集X={x1,···,xn}上的一组子句C1,···,Ck,问存在满足的真值赋值吗?

注意:每个子句均为析取子句(逻辑或∨),最终结果为各个子句的合取(逻辑与∧)。


6、3-SAT(三元可满足性问题)——给定bool变量集X={x1,···,xn}上的一组子句C1,···,Ck,每个子句的长为3,问存在满足的真值赋值吗?

注意:同上。


常用引理

设G=(V, E)是一个图,S?V,那么S是一个独立集当且仅当它的补V-S是一个顶点覆盖。

证明:首先,设S是一个独立集。考虑任一边e=(u,v),因为S是独立集,u和v不可能同时在S中,所以u和v至少有一个在V-S中,即得任一边至少有一个端点在V-S中,所以V-S是一个顶点覆盖。

反过来,设V-S是一个顶点覆盖,考虑S中的任意两个顶点u、v,若它们间有一条边e,那么e的两个端点均不在V-S中,这与假设V-S是一个顶点覆盖矛盾。所以S中的任意两点均无连线,所以S是一个独立集。


常见归约问题

归约的一般思想(要点):证明Y到X的归约,要用问题X中的分量构造“零件”来描写在问题Y中正在做的事

1、 独立集归约到顶点覆盖

证明:若有一个解顶点覆盖的黑盒子,那么通过问黑盒子G是否有大小至多为n-k的顶点覆盖,就能确定G是否有大小至少为k的独立集。


2、顶点覆盖归约到独立集

证明:若有一个可以解独立集的黑盒子,那么通过问黑盒子G是否有大小至少为n-k的独立集,就能确定G是否有大小至多为k的顶点覆盖。


3、顶点覆盖归约到集合覆盖

证明:若有一个可以解集合覆盖的黑盒子,考虑顶点覆盖的任一实例,给定图G=(V, E)和数k。

构造集合覆盖的一个实例,其基集U等于边E,对图G的每一个顶点i∈V,设Si?U为G中所有和点i相关联的边,把Si加入集合覆盖的实例中。

U能被集合S1,S2,···,Sn中的至多k个覆盖当且仅当G有大小至多为k的顶点覆盖。于是,给定顶点覆盖的实例,如上述的那样构造集合覆盖的实例,并把它输入黑盒子。回答yes当且仅当黑盒子回答yes。


4、独立集归约到集合包装

证明:若有一个解集合包装的黑盒子,考虑独立集的任一实例,给定图G=(V,E)和数k。

构造集合包装的一个实例,其基集U等于边E,对图G的每一个顶点i∈V,设Si?U为G中所有不和点i相关联的边,把Si加入集合包装的实例中。

U的子集S1,S2,···,Sn(实际是n个边集合)中至少k个两两不相交(即不存在相同边)当且仅当G有大小至少为k的独立集(此时k个顶点必不存在相连边),于是,给定独立集的实例,如上述的那样构造集合包装的实例,并把它输入黑盒子。回答yes当且仅当黑盒子回答yes。


5、3-SAT归约到独立集

证明:设有一个解独立集的黑盒子,要解3-SAT的实例,实例由变量集X={x1,····,xn}和子句C1,····,Ck组成。

考虑3-SAT的方法是:必须从每一个子句中选择一个项,然后找一组真值赋值使得所有找出来的项都为1,从而满足所有的子句。因此,如果如果没有两个被选中的项冲突,那么就成功了。

具体归约:用独立集描述3-SAT实例。首先,构造图G=(V,E),它由分成k个三角形的3k个顶点组成,如下图所示。对每一个子句i,构造3个顶点vi1,vi2,vi3。依据3-SAT实例子句在图中增加边描述冲突:在每一对标号对应冲突的项的顶点间添加一条边。

要证明原来的3-SAT是可满足的当且仅当构造出来的图G(依据3-SAT的实例子句构造)有大小至少为k的独立集。

>首先,若3-SAT是可满足的,那么构造出来的图G中的每个三角形至少包含一个标号的值为1的顶点。设S是每一个三角形中的一个这样的顶点组成的集合。设S不是一个独立集,则至少存在两个顶点u、v∈S间有一条边,则u、v一定是冲突(一个是1,另一个必是0)的,而S中的每个点值都为1,所以矛盾,所以假设不成立,即S是一个独立集。

>反过来,设图G有一个大小至少为k的独立集S。那么,当S的大小恰好为k,那么一定是由每个三角形的一个顶点组成,且S中的冲突顶点最多只能成单出现。所以显然可以设S中所有顶点对应的值全为1,且这些顶点每个对应于一个子句中选择的代表,所以此时对应的3-SAT实例存在真值赋值。

时间: 2024-10-07 06:39:42

算法导论之P、NP、NPC问题的相关文章

P NP NPC的通俗解释

这或许是众多OIer最大的误区之一.    你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜了,这已经被证明是NP问题 了”之类的话.你要知道,大多数人此时所说的NP问题其实都是指的NPC问题.他们没有搞清楚NP问题和NPC问题的概念.NP问题并不是那种“只有搜才 行”的问题,NPC问题才是.好,行了,基本上这个误解已经被澄清了.下面的内容都是在讲什么是P问题,什么是NP问题,什么是NPC问题,你如果不是很 感兴趣就可以不看了.接下来你可以看到,把NP问题当成是 NPC问题是一个

算法导论——基础知识(1)

算法定义: 描述一个特定的计算过程来实现输入输出关系 ps:通俗的说就是对给定的输入数据进行计算,得到一个正确的输出. 既然是一个过程吗,那么有效率问题,比如我们算1..n的和, 我们可以这样 sum = 1+2+..+n 也可以这样 sum = n(1+n)/2 实际表现为时间复杂度和空间复杂度 数据结构: 存储.组织数据的方式 ps:比如说一个学生,ta有学号.姓名等属性,那么我们可以这样定义一个学生类别 Student { name number }   ps:书中说道的NP问题,贴上一个

算法导论 之 动态规划 - 矩阵链相乘

1 引言 在大学期间,我们学过高等数学中的线性规划,其中有关于矩阵相乘的章节:只有当矩阵A的列数与矩阵B的行数相等时,A×B才有意义.一个m×n的矩阵A(m,n)左乘一个n×p的矩阵B(n,p),会得到一个m×p的矩阵C(m,p).矩阵乘法满足结合律,但不满足交换律. 假设现要计算A×B×C×D的值,因矩阵乘法满足结合律,不满足交换律,即:A.B.C.D相邻成员的相乘顺序不会影响到最终的计算结果,比如: A×(B×(C×D)).A×((B×C)×D).(A×B)×(C×D).A×(B×C)×D.

《算法导论》----------什么是算法?

何为算法? 算法,一个让我们听起来熟悉有陌生的词汇.很多刚毕业的大学生毕业的时候,在参加bat的面试,必不可少的两项,数据结构+算法. 那么什么是算法呢,今天就让我们跟着<算法导论>这本书,一起去翱翔算法的世界. 算法,顾名思义,就是计算的方法,这个计算是个很广义的词汇,可以指我们生活中买菜的计算,可以指我们程序中编程解法的计算,总之,算法是一个无所不在的东西.无论是我们的生活中还是工作中,都离不开算法. 生活中的算法: 相信大家小时候都做过这样的事情,就是妈妈给我们1块钱,这一块钱是我们一天

算法导论——lec 11 动态规划及应用

和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互独立的情况,即各个子问题包含公共的子子问题.在这种情况下,如果用分治法会多做许多不必要的工作,重复求解相同的子子问题.而动态规划将每个子问题的解求解的结果放在一张表中,避免了重复求解. 一. 动态规划介绍 1. 动态规划方法介绍: 动态规划主要应用于最优化问题, 而这些问题通常有很多可行解,而我们希

《算法导论》图相关算法小结

最近又抽空读了一遍<算法导论>,关于图的内容贯穿了多个章节(比如在动态规划一章埋了无权最短路径的伏笔,后面才专门讲),适用条件各异,而且都有证明过程. 如果不打算熟记证明,仅仅是应用,遇到具体场景再去回忆适用于哪种算法不太方便. 以下内容以手头的机械工业出版社基于原书第2版的译本整理了一下,便于速查. 不包含思考题.标注为"*"的章节和习题内容. 符号定义 一般地, 图G=(V, E),其中V代表顶点集合,E代表边集合.ω(u, v)代表从顶点u到顶点v的边的权值. 如果ω

算法导论学习之插入排序+合并排序

最近准备花时间把算法导论详细的看一遍,强化一下算法和数据结构的基础,将一些总结性的东西写到博客上去. 一.插入排序 算法思想:如果一个数组A,从A[1–n-1]都是有序的,然后我们将A[n]插入到A[1–n-1]的某个合适的位置上去那么就可以保证A[1–n]都是有序的.这就是插入排序的思想:具体实现的时候我们将数组的第一个元素看出有序,然后从第二个元素开始按照上面的步骤进行插入操作,直到插入最后一个元素,然后整个数组都是有序的了. 时间复杂度分析:代码中有两重for循环,很容易看出时间复杂度是n

算法导论——lec 13 贪心算法与图上算法

之前我们介绍了用动态规划的方法来解决一些最优化的问题.但对于有些最优化问题来说,用动态规划就是"高射炮打蚊子",采用一些更加简单有效的方法就可以解决.贪心算法就是其中之一.贪心算法是使所做的选择看起来是当前最佳的,期望通过所做的局部最优选择来产生一个全局最优解. 一. 活动选择问题 [问题]对几个互相竞争的活动进行调度:活动集合S = {a1, a2, ..., an},它们都要求以独占的方式使用某一公共资源(如教室),每个活动ai有一个开始时间si和结束时间fi ,且0 ≤ si &

算法导论--图的遍历(DFS与BFS)

转载请注明出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51897538 图的遍历就是从图中的某个顶点出发,按某种方法对图中的所有顶点访问且仅访问一次.为了保证图中的顶点在遍历过程中仅访问一次,要为每一个顶点设置一个访问标志.通常有两种方法:深度优先搜索(DFS)和广度优先搜索(BFS).这两种算法对有向图与无向图均适用. 以下面无向图为例: 1.深度优先搜索(DFS) 基本步骤: 1.从图中某个顶点v0出发,首先访问v

算法导论8:数据结构——栈 2016.1.8

栈在暑假的时候接触过了,当时还写了个计算器,用的中缀表达式后缀表达式的栈操作. http://www.cnblogs.com/itlqs/p/4749998.html 今天按照算法导论上的讲解规范了一下代码.主要是栈的初始化.判断空栈.入栈.出栈.遍历栈. #include<stdio.h> #define MAXTOP 10 struct _stack { int top; int num[MAXTOP+1]; }s; void init(struct _stack &S) { S.