本章首先介绍一个对问题进行抽象的典型实例——哥尼斯堡七桥问题。然后,通过“梵天塔”问题和“停机问题”分别介绍学科中的可计算问题和不可计算问题。从“梵天塔”问题再引出算法复杂性中的难解性问题、P类问题和NP类问题,证比求易算法,P=NP是否成立的问题。1哥尼斯堡七桥问题17世纪的东普鲁士有一座哥尼斯堡城,城中有一座奈佛夫岛,普雷格尔河的两条支流环绕其旁,并将整个城市分成北区、东区、南区和岛区4个区域,全城共有7座桥将4个城区相连起来。通过这7座桥到各城区游玩,问题:寻找走遍这7座桥的路径,要求过每座桥只许走一次,最后又回到原出发点。岛区北区南区东区问题的抽象1736年,大数学家列昂纳德·欧拉(L.Euler)发表了关于“哥尼斯堡七桥问题”的论文。他抽象出问题最本质的东西,忽视问题非本质的东西(如桥的长度等),从而将哥尼斯堡七桥问题抽象为一个数学问题,即经过图中每边一次且仅一次的回路问题了。DCBA欧拉回路欧拉给出了哥尼斯堡七桥问题的证明,还用数学方法给出了三条判定规则(判定每座桥恰好走过一次,不一定回到原点,即对欧拉路径的判定):如果通奇数座桥的地方不止两个,满足要求的路线是找不到的。如果只有两个地方通奇数座桥,可以从这两个地方之一出发,找到所要求的路线。如果没有一个地方是通奇数座桥的,则无论从哪里出发,所要求的路线都能实现。根据第3点,可以得出,任一连通图存在欧拉回路的充分必要条件是所有顶点均有偶数度.哈密尔顿回路问题问题:在某个图G中,能不能找到这样的路径,即从一点出发不重复地走过所有的结点,最后又回到原出发点。“哈密尔顿回路问题”与“欧拉回路问题”的不同点“哈密尔顿回路问题”是访问每个结点一次,而“欧拉回路问题”是访问每条边一次。对图G是否存在“欧拉回路”前面已给出充分必要条件,而对图G是否存在“哈密尔顿回路”至今仍未找到满足该问题的充分必要条件。图论的形成和发展欧拉的论文为图论的形成奠定了基础。图论已广泛地应用于计算学科运筹学信息论控制论等学科图论已成为我们对现实问题进行抽象的一个强有力的数学工具。图论在计算学科中的作用越来越大,图论本身也得到了充分的发展。2可计算问题与不可计算问题计算学科的问题,无非就是计算问题,从大的方面来说,分可计算问题与不可计算问题。可计算问题是存在算法可解的问题,不可计算问题是不存在算法可解的问题。为便于理解,下面,分别以梵天塔(Hanoi,又译为汉诺)问题和停机问题来介绍可计算问题与不可计算问题。2.1排序问题随机给出n个数,要求对它们进行排序。比如:8,2,7,6,4,12对于排序问题,有多种算法。一种选择排序算法是:从n个数中挑出最小的数,再从n-1个数中挑出第二小的数…..那么,在这些众多的算法中,如何来比较谁的速度更快?事后分析:机器的运行时间?事前分析:与问题规模有关的表达式,表示算法中基本操作的执行次数。一种选择排序算法是:从n个数中挑出最小的数,再从n-1个数中挑出第二小的数…..时间复杂性与n有关,大概是n+(n-1)+…+1=1/2(n(n+1)),忽略常数项,取最大的指数,记为O(n2)。最快的算法是快速排序算法,时间复杂度为O(nlogn)。2.2梵天塔问题相传印度教的天神梵天在创造地球这一世界时,建了一座神庙,神庙里竖有三根宝石柱子,柱子由一个铜座支撑。梵天将64个直径大小不一的金盘子,按照从大到小的顺序依次套放在第一根柱子上,形成一座金塔(如图2.3所示),即所谓的梵天塔(又称汉诺塔)。天神让庙里的僧侣们将第一根柱子上的64个盘子借助第二根柱子全部移到第三根柱子上,即将整个塔迁移,同时定下3条规则:每次只能移动一个盘子;盘子只能在三根柱子上来回移动,不能放在他处;在移动过程中,三根柱子上的盘子必须始终保持大盘在下,小盘在上。12递归算法(重点掌握)递归是一种特别有用的工具,不仅在数学中广泛应用,在日常生活中也常常遇到。以下使用递归算法来解决梵塔问题。13递归算法在数学中几个熟知的数学定义:1)!1(01!)1(nnnnn(2)若t1,t2是树,则也是树t1t21101)3(111nCCnmnCnmnmnm14递归递归算法包括递推和回归两部分:递推就是为了得到问题的解,将它推到比原问题更简单的问题求解。例如:n!=f(n),为了计算f(n),将它推到比原问题更简单的问题f(n-1),即f(n)=f(n-1)*n,而计算f(n-1)比计算f(n)简单,因为f(n-1)比f(n)更加接近已知解0!=1使用递推要注意(1)递推应有终止之时,例如当n=0时,0!=1为递推终止条件,所谓终止条件就是指在此条件下问题的解时明确的,缺少终止条件会使算法失败。(2)简单问题表示离递推终止条件更接近的问题。简单的问题与原问题其解的算法是一致的,其差别主要反映在参数上,例如,f(n-1)比计算f(n)更简单,因为f(n-1)比f(n)参数少1。参数变化使问题递推到有明确解。15递归算法回归指当简单问题得到解后,回归到原问题的解上来。例如,当计算完(n-1)!后,回归计算n*(n-1)!,即得到n!的值。使用回归要注意(1)当回归到原问题的解时,算法中所涉及的处理对象是关于当前问题的,即递归算法所涉及的参数与局部处理对象是有层次的。当解一问题的时候,有它的一套参数与局部处理对象。当递推进入一个简单问题的时候。这套参数与局部对象便隐藏起来,在解简单问题的时候又有它自己的一套。当回归时,原问题的一套参数与局部处理对象又活跃起来了。(2)回归到原问题已经得到问题的解,回归并不引起其他动作。16递归的例子计算n!根据公式n!=1当n=0=n*(n-1)!当n!=0函数参数为nintf(intn){if(!n)return1;elsereturn(n*f(n-1));}17递归的例子斐波那契数列(fibonacci)f(0)=0f(1)=1f(n)=f(n-1)+f(n-2)(n=2)intf(intn){if(!n)return0;elseif(n==1)return1;elsereturn(f(n-1)+f(n-2));}18梵塔问题算法分析:用A、B、C分别表示三根针将n个盘由A移到C上的操作步骤为:(1)将A上的n-1个盘借助C移到B上(2)把A上剩下的一个盘由A移到C上(3)将B上的n-1个盘借助A移到C上这样处理后,问题的规模减少1。当n=1的时候,就可以直接处理了。19穷举演算n=3ABCABCABCABC(1)(2)ATOC(3)ATOB(4)CTOB20穷举演算(续)ABC(5)ATOCABCABCABC(6)BTOA(7)BTOC(8)ATOC21梵塔问题:子程序/*程序HANOI.C:梵塔问题-*/#includestdio.h#defineN3voidmove(intfrom,intto){printf(From%cto%c\n,from,to);}voidhanoi(intn,intp1,intp2,intp3){if(n==1)move(p1,p3);else{hanoi(n-1,p1,p3,p2);move(p1,p3);hanoi(n-1,p2,p1,p3);}}/*测试用主函数*/main(){hanoi(N,'A','B','C');}当n=64时,移动次数=?花费时间=?h(n)=2h(n-1)+1=2(2h(n-2)+1)+1=22h(n-2)+2+1=23h(n-3)+22+2+1……=2nh(0)+2n-1+…+22+2+1=2n-1+…+22+2+1=2n-1需要移动盘子的次数为:264-1=18446744073709551615假定每秒移动一次,一年有31536000秒,则僧侣们一刻不停地来回搬动,也需要花费大约5849亿年的时间。假定计算机以每秒1000万个盘子的速度进行搬迁,则需要花费大约58490年的时间。这样的问题也称为难解问题,虽然理论上可以解决,但是在n值比较大的情况下,计算时间太大。对于此类问题,人类也一直在寻找是否有更快的计算算法。2.3算法复杂性中的难解性问题、P类问题和NP类问题算法复杂性包括算法的空间以及时间两方面的复杂性问题,梵天塔问题主要讲的是算法的时间复杂性。关于梵天塔问题算法的时间复杂度,可以用一个指数函数O(2n)来表示,显然,当n很大(如10000)时,计算机是无法处理的。相反,当算法的时间复杂度的表示函数是一个多项式,如O(n2)时,则可以处理。因此,一个问题求解算法的时间复杂度大于多项式(如指数函数)时,算法的执行时间将随n的增加而急剧增长,以致即使是中等规模的问题也不能求解出来,于是在计算复杂性中,将这一类问题称为难解性问题。人工智能领域中的状态图搜索问题(解空间的表示或状态空间搜索问题)就是一类典型的难解性问题。在计算复杂性理论中,将所有可以在多项式时间内求解的问题称为P类问题,而将所有在多项式时间内可以验证的问题称为NP类问题。由于P类问题采用的是确定性算法,NP类问题采用的是非确定性算法,而确定性算法是非确定性算法的一种特例,因此,可以断定PNP。2.4证比求易算法为了更好地理解计算复杂性的有关概念,我国学者洪加威曾经讲了一个被人称为“证比求易算法”的童话,用来帮助读者理解计算复杂性的有关概念,大致内容如下。从前,有一个酷爱数学的年轻国王艾述向邻国一位聪明美丽的公主秋碧贞楠求婚。公主出了这样一道题:求出48770428433377171的一个真因子。若国王能在一天之内求出答案,公主便接受他的求婚。国王回去后立即开始逐个数地进行计算,他从早到晚,共算了三万多个数,最终还是没有结果。国王向公主求情,公主将答案相告:223092827是它的一个真因子。国王很快就验证了这个数确能除尽48770428433377171。公主说:“我再给你一次机会,如果还求不出,将来你只好做我的证婚人了。”国王立即回国,并向时任宰相的大数学家孔唤石求教,大数学家在仔细地思考后认为这个数为17位,则最小的一个真因子不会超过9位,他给国王出了一个主意:按自然数的顺序给全国的老百姓每人编一个号发下去,等公主给出数目后,立即将它们通报全国,让每个老百姓用自己的编号去除这个数,除尽了立即上报,赏金万两。顺序算法和并行算法国王最先使用的是一种顺序算法,其复杂性表现在时间方面,后面由宰相提出的是一种并行算法,其复杂性表现在空间方面。直觉上,我们认为顺序算法解决不了的问题完全可以用并行算法来解决,甚至会想,并行计算机系统求解问题的速度将随着处理器数目的不断增加而不断提高,从而解决难解性问题,其实这是一种误解。当将一个问题分解到多个处理器上解决时,由于算法中不可避免地存在必须串行执行的操作,从而大大地限制了并行计算机系统的加速能力。阿达尔定律设f为求解某个问题的计算存在的必须串行执行的操作占整个计算的百分比,p为处理器的数目,Sp为并行计算机系统最大的加速能力,则设f=1%,p→,则Sp=100。串行执行操作仅占全部操作1%,解题速度最多也只能提高一百倍。对难解性问题而言,提高计算机系统的速度是远远不够的,而降低算法复杂度的数量级才是最关键的问题。2.5P=NP?P类问题——存在多项式时间的算法的一类问题;NP类问题——非多项式时间算法解的一类问题。像梵塔问题、推销员旅行问题、(命题表达式)可满足问题这类,至今没有找到多项式时间算法解的一类问题。P=NP?如果P=NP,则所有在多项式时间内可验证的问题都将是在多项式时间内可求解(或可判定)的问题。要证明P≠NP,目前还无法做到这一点。NP完全问题在P=?NP问题上,库克(S.A.Cook)等人认为NP类中的某些问题的复杂性与整个类的复杂性有关,当这些问题中的任何一个存在多项式时间算法时,则所有这些NP问题都是多项式时间可解的,这些问题被称为NP完全性问题。多达数千个的NP