转自:http://www.cnblogs.com/chinazhangjie/archive/2010/12/06/1898070.html

一、图灵机

根据有限状态控制器的当前状态及每个读写头读到的带符号,图灵机的一个计算步可实现下面3个操作之一或全部。

(1)改变有限状态控制器中的状态。

(2)清除当前读写头下的方格中原有带符号并写上新的带符号。

(3)独立地将任何一个或所有读写头,向左移动一个方格(L)或向右移动一个方格(R)或停在当前单元不动(S)。

k带图灵机可形式化地描述为一个7元组(Q,T,I,δ,b,q0,qf),其中:

(1) Q是有限个状态的集合。

(2)T是有限个带符号的集合。

(3)I是输入符号的集合

(4)b是唯一的空白符,b∈T-I。

(5)q0是初始状态。

(6)qf是终止(或接受)状态。

(7)δ是转移函数。

它是从Q×Tk的某一子集映射到Q×(T×{L,R,S})k的函数。

图灵机M的时间复杂性T(n)是它处理所有长度为n的输入所需的最大计算步数。如果对某个长度为n的输入,图灵机不停机,T(n)对这个n值无定义。

图灵机的空间复杂性S(n)是它处理所有长度为n的输入时,在k条带上所使用过的方格数的总和。如果某个读写头无限地向右移动而不停机,S(n)也无定义。

确定型图灵机

有限状态集Q,状态q0:初始状态;qy:接受状态;状态qn:不接受状态。

字符集合{0, 1, b} ;其中b是空格符。

转换功能:

输入x = 101000b

执行顺序:

q0输入1 (q0,r)右移磁头到0

q0输入0 (q0,r)右移磁头到1

q0输入0 (q0,r)右移磁头到0

...

q0输入b (q1,l)左移磁头到0

q1输入0 (q2,b)

q2输入b (q2,l)左移磁头到0

q2输入0 (q3,b)

q3输入b (qy,l)退出

二、P类与NP类问题

一般地说,将可由多项式时间算法求解的问题看作是易处理的问题,而将需要超多项式时间才能求解的问题看作是难处理的问题。

有许多问题,从表面上看似乎并不比排序或图的搜索等问题更困难,然而至今人们还没有找到解决这些问题的多项式时间算法,也没有人能够证明这些问题需要超多项式时间下界。

在图灵机计算模型下,这类问题的计算复杂性至今未知。

为了研究这类问题的计算复杂性,人们提出了另一个能力更强的计算模型,即非确定性图灵机计算模型,简记为NDTM(Nondeterministic Turing Machine)。

在非确定性图灵机计算模型下,许多问题可以在多项式时间内求解。

非确定性图灵机

在图灵机计算模型中,移动函数δ是单值的,即对于QxTk中的每一个值,当它属于δ的定义域时,Qx(Tx{L,R,S})k中只有唯一的值与之对应,称这种图灵机为确定性图灵机,简记为DTM(Deterministic Turing Machine)。

非确定性图灵机(NDTM):一个k带的非确定性图灵机M是一个7元组:(Q,T,I,δ,b,q0,qf)。与确定性图灵机不同的是非确定性图灵机允许移动函数δ具有不确定性,即对于Q×Tk中的每一个值(q;x1,x2,…,xk),当它属于δ的定义域时,Q×(T×{L,R,S})k中有唯一的一个子集δ(q;x1,x2,…,xk)与之对应。可以在δ(q;x1,x2,…,xk)中随意选定一个值作为它的函数值。

P类与NP类语言定义

P={L|L是一个能在多项式时间内被一台DTM所接受的语言}

NP={L|L是一个能在多项式时间内被一台NDTM所接受的语言}

由于一台确定性图灵机可看作是非确定性图灵机的特例,所以可在多项式时间内被确定性图灵机接受的语言也可在多项式时间内被非确定性图灵机接受。故P Í NP。

NP类语言举例——无向图的团问题

该问题的输入是一个有n个顶点的无向图G=(V,E)和一个整数k。要求判定图G是否包含一个k顶点的完全子图(团),即判定是否存在V’V,|V’|=k,且对于所有的u,v∈V’,有(u,v)∈E。

若用邻接矩阵表示图G,用二进制串表示整数k,则团问题的一个实例可以用长度为n2+logk+1的二进位串表示。因此,团问题可表示为语言:

CLIQUE={w#v|w,v∈{0,1}*,以w为邻接矩阵的图G有一个k顶点的团,其中v是k的二进制表示。}

接受该语言CLIQUE的非确定性算法:用非确定性选择指令选出包含k个顶点的候选顶点子集V,然后确定性地检查该子集是否是团问题的一个解。算法分为3个阶段

算法的第一阶段将输入串w#v分解,并计算出n = ,以及用v表示的整数k。若输入不具有形式w#v或|w|不是一个平方数就拒绝该输入。显而易见,第一阶段可在时间内完成。

在算法的第二阶段中,非确定性地选择V的一个k元子集V’V。

算法的第三阶段是确定性地检查V’的团性质。若V’是一个团则接受输入,否则拒绝输入。这显然可以在时间内完成。因此,整个算法的时间复杂性为 

非确定性算法在多项式时间内接受语言CLIQUE,故CLIQUE∈NP.

NP完全问题

PNP。

直观上看,P类问题是确定性计算模型下的易解问题类,而NP类问题是非确定性计算模型下的易验证问题类。

大多数的计算机科学家认为NP类中包含了不属于P类的语言,即P≠NP。

NP完全问题有一种令人惊奇的性质,即如果一个NP完全问题能在多项式时间内得到解决,那么NP中的每一个问题都可以在多项式时间内求解,即P = NP。

目前还没有一个NP完全问题有多项式时间算法。

三、NP完全问题的近似算法

迄今为止,所有的NP完全问题都还没有多项式时间算法。

对于这类问题,通常可采取以下几种解题策略。

(1)只对问题的特殊实例求解

(2)用动态规划法或分支限界法求解

(3)用概率算法求解

(4)只求近似解

(5)用启发式方法求解

近似算法的性能

若一个最优化问题的最优值为c*,求解该问题的一个近似算法求得的近似最优解相应的目标函数值为c,则将该近似算法的性能比定义为(注意:求最大值与最小值的性能比定义之间的不同)。

怎么理解那个Ratio Bound呢?第一点明白OPT是最优解,我们的近似解不可能优于它,所以对于最大化问题,A一定比OPT小而对于最小化问题A一定比OPT大,所以上面的连个max取了不同的值。注意这里的Ratio Bound指的是那个B(n),即是max{A/OPT, OPT/A}的上界。

在通常情况下,该性能比是问题输入规模n的一个函数ρ(n),即

该近似算法的相对误差定义为:。若对问题的输入规模n,有一函数ε(n)使得则称ε(n)为该近似算法的相对误差界。近似算法的性能比ρ(n)与相对误差界ε(n)之间显然有如下关系:

旅行售货员问题近似算法

问题描述:给定一个完全无向图G=(V,E),其每一边(u,v)∈E有一非负整数费用c(u,v)。要找出G的最小费用哈密顿回路。

旅行售货员问题的一些特殊性质:

比如,费用函数c往往具有三角不等式性质,即对任意的3个顶点u,v,w∈V,有:c(u,w)≤c(u,v)+c(v,w)。当图G中的顶点就是平面上的点,任意2顶点间的费用就是这2点间的欧氏距离时,费用函数c就具有三角不等式性质。

1  满足三角不等式的旅行售货员问题

对于给定的无向图G,可以利用找图G的最小生成树的算法设计找近似最优的旅行售货员回路的算法。

void approxTSP (Graph g)

{

(1)选择g的任一顶点r;

(2)用Prim算法找出带权图g的一棵以r为根的最小生成树T;

(3)前序遍历树T得到的顶点表L;

(4)将r加到表L的末尾,按表L中顶点次序组成回路H,作为计 算结果返回;

}

当费用函数满足三角不等式时,算法找出的旅行售货员回路的费用不会超过最优旅行售货员回路费用的2倍。

实现:

代码

/* 主题:近似算法——旅行售货员问题
* 作者:chinazhangjie
* 邮箱:chinajiezhang@gmail.com
* 开发语言: C++
* 开发环境: Virsual Studio 2005
* 时间: 2010.12.06
*/ #include <iostream>
#include <vector>
#include <limits>
using namespace std ; struct TreeNode
{
public:
TreeNode (int nVertexIndexA = , int nVertexIndexB = , int nWeight = )
: m_nVertexIndexA (nVertexIndexA),
m_nVertexIndexB (nVertexIndexB),
m_nWeight (nWeight)
{ }
public:
int m_nVertexIndexA ;
int m_nVertexIndexB ;
int m_nWeight ;
} ; class MST_Prim
{
public:
MST_Prim ()
{}
MST_Prim (const vector<vector<int> >& vnGraph)
{
m_nvGraph = vnGraph ;
m_nNodeCount = (int)m_nvGraph.size () ;
}
void SetData (const vector<vector<int> >& vnGraph)
{
m_nvGraph = vnGraph ;
m_nNodeCount = (int)m_nvGraph.size () ;
}
//
const vector<TreeNode>& GetMSTree () const
{
return m_tnMSTree ;
}
//
const vector<vector<int> >& GetGraph () const
{
return m_nvGraph ;
}
void DoPrim ()
{
// 是否被访问标志
vector<bool> bFlag (m_nNodeCount, false) ;
bFlag[] = true ; int nMaxIndexA ;
int nMaxIndexB ;
int j = ;
while (j < m_nNodeCount - ) {
int nMaxWeight = numeric_limits<int>::max () ;
// 找到当前最短路径
int i = ;
while (i < m_nNodeCount) {
if (!bFlag[i]) {
++ i ;
continue ;
}
for (int j = ; j < m_nNodeCount; ++ j) {
if (!bFlag[j] && nMaxWeight > m_nvGraph[i][j]) {
nMaxWeight = m_nvGraph[i][j] ;
nMaxIndexA = i ;
nMaxIndexB = j ;
}
}
++ i ;
}
bFlag[nMaxIndexB] = true ;
m_tnMSTree.push_back (TreeNode(nMaxIndexA, nMaxIndexB, nMaxWeight)) ;
++ j ;
}
// 输出结果
/*for (vector<TreeNode>::const_iterator ite = m_tnMSTree.begin() ;
ite != m_tnMSTree.end() ;
++ ite ) {
cout << (*ite).m_nVertexIndexA << "->"
<< (*ite).m_nVertexIndexB << " : "
<< (*ite).m_nWeight << endl ;
}*/
} private:
vector<vector<int> > m_nvGraph ; // 无向连通图
vector<TreeNode> m_tnMSTree ; // 最小生成树
int m_nNodeCount ;
} ; class AA_TSP
{
public:
AA_TSP (const vector<vector<int> >& vnGraph)
{
m_mstPrim.SetData(vnGraph) ;
}
void Get_AA_Path ()
{
m_mstPrim.DoPrim () ;
vector<TreeNode> mstree = m_mstPrim.GetMSTree () ;
vector<vector<int> > graph = m_mstPrim.GetGraph() ;
int iweight = ;
for (vector<TreeNode>::const_iterator ite = mstree.begin() ;
ite != mstree.end() ;
++ ite ) {
cout << (*ite).m_nVertexIndexA << "->"
<< (*ite).m_nVertexIndexB << " : "
<< (*ite).m_nWeight << endl ;
iweight += (*ite).m_nWeight ;
}
cout << mstree[mstree.size()-].m_nVertexIndexB << "->"
<< mstree[].m_nVertexIndexA << " : "
<< graph[mstree[].m_nVertexIndexA][mstree[mstree.size()-].m_nVertexIndexB]
<< endl ;
iweight += graph[mstree[].m_nVertexIndexA][mstree[mstree.size()-].m_nVertexIndexB] ;
cout << "Total weight: " << iweight << endl ;
}
private:
MST_Prim m_mstPrim ;
};
int main()
{
const int cnNodeCount = ;
vector<vector<int> > graph (cnNodeCount) ;
for (size_t i = ; i < graph.size() ; ++ i) {
graph[i].resize (cnNodeCount, numeric_limits<int>::max()) ;
}
graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; graph[][] = ;
graph[][] = ;
graph[][] = ;
graph[][] = ; AA_TSP aa (graph) ;
aa.Get_AA_Path () ;
return ;
}

2  一般的旅行售货员问题

在费用函数不一定满足三角不等式的一般情况下,不存在具有常数性能比的解TSP问题的多项式时间近似算法,除非P=NP。换句话说,若P≠NP,则对任意常数ρ>1,不存在性能比为ρ的解旅行售货员问题的多项式时间近似算法。

NP完全性理论与近似算法的更多相关文章

  1. 什么是P问题、NP问题和NPC问题

    为了迎接我的期末考试,认真的看了一下关于NP完全性理论这一章,奈何课本上说的我怎么都看不懂,所以找了个博客认真研究了一下,同样贴出来分享给大家,大牛就是大牛,把问题说的很明白,看完后受益匪浅.其中有一 ...

  2. p,np,npc,np难问题,确定图灵机与非确定图灵机

    本文转自豆瓣_燃烧的影子 图灵机与可计算性 图灵(1912~1954)出生于英国伦敦,19岁进入剑桥皇家学院研究量子力学和数理逻辑.1935年,图灵写出了"论高斯误差函数"的论文, ...

  3. 关于P,NP,NPC和NP-hard的通俗解释

    这些概念以前老是犯糊涂,今天整清楚.摘要:P: Polynomial SolvableNP: Non-determinstic Polynomial Solvable 0)词语解释:Polynomia ...

  4. Google Interview University - 坚持完成这套学习手册,你就可以去 Google 面试了

    作者:Glowin链接:https://zhuanlan.zhihu.com/p/22881223来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 原文地址:Google ...

  5. 算法设计手冊(第2版)读书笔记, Springer - The Algorithm Design Manual, 2ed Steven S.Skiena 2008

    The Algorithm Design Manual, 2ed 跳转至: 导航. 搜索 Springer - The Algorithm Design Manual, 2ed Steven S.Sk ...

  6. 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)

    第一部分 基础知识 第1章 算法在计算中的作用 第2章 算法基础 第3章 函数的增长 第4章 分治策略 第5章 概率分析和随机算法 第二部分 排序和顺序统计量 第6章 堆排序 第7章 快速排序 第8章 ...

  7. 贪婪算法(Greedy Algorithm)

    Greedy Algorithm <数据结构与算法--C语言描述> 图论涉及的三个贪婪算法 Dijkstra 算法 Prim 算法 Kruskal 算法 Greedy 经典问题:coin ...

  8. 【转载】 历届Turing奖得主名单

    Turing奖最早设立于1966年,是美国计算机协会在计算机技术方面所授予的最高奖项,被喻为计算机界的诺贝尔奖.它是以英国数学天才Alan Turing先生的名字命名的,Alan Turing先生对早 ...

  9. 历届图灵奖 (Turing award)得奖名单

    历届图灵奖 (Turing award)得奖名单 一.总结 一句话总结:各个方面都有. 二.历届图灵奖 (Turing award)得奖名单 Turing奖最早设立于1966年,是美国计算机协会在计算 ...

随机推荐

  1. SpringBatch Sample (四)(固定长格式文件读写)

    前篇关于Spring Batch的文章,讲述了Spring Batch 对XML文件的读写操作. 本文将通过一个完整的实例,与大家一起讨论运用Spring Batch对固定长格式文件的读写操作.实例延 ...

  2. Spring Batch框架流程的简单介绍

    Spring Batch流程介绍: 上图描绘了Spring Batch的执行过程.说明如下: 每个Batch都会包含一个Job.Job就像一个容器,这个容器里装了若干Step,Batch中实际干活的也 ...

  3. 纯C MD5

    尼玛WordPress把格式全搞乱了 md5.h #ifndef __MD5_H__ #define __MD5_H__ #ifndef _CRT_SECURE_NO_WARNINGS #define ...

  4. sql ''增删改'' 笔记

    结构语言分类 DDL(数据定义语言)  create  drop  alter   创建删除以及修改数据库,表,存储过程,触发器,索引.... DML(数据操作语言)   insert  delete ...

  5. Unity射线检测的用法总结

    RayCast 射线检测 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享.心 ...

  6. js知识点: 数组

    1.行内元素  margin  padding 左右值都有效,上下值都无效 2.var ev = ev || window.event document.documentElement.clientW ...

  7. 2017.4.9 函数式编程FP

    函数编程(简称FP)不只代指Haskell Scala等之类的语言,还表示一种编程范式,和面向对象的编程方式一样,是编程思维,软件思考方式,也称面向函数编程. 编程的本质是组合,组合的本质是范畴Cat ...

  8. C++学习(三十四)(C语言部分)之 链表

    1.栈和队列 操作 增查改删重点 插入删除先进先出 -->队列先进后出 -->栈2.链表 写之前先画图存储数据的方式 通过指针将所有的数据链在一起数据结构的目的 管理存储数据 方便快速查找 ...

  9. hdu4338 Simple Path

    Everybody knows that totalfrank has absolutely no sense of direction. Getting lost in the university ...

  10. 取消svn关联文件夹

    svn没有自带取消svn关联功能,所以我们需要以下脚本 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classe ...