1、算法分析与设计实验报告第 七 次附加实验姓名 学号 班级时间 12.26 上午 地点 工训楼 309实验名称 回溯法实验(最大团问题)实验目的 1. 掌握回溯法求解问题的思想2. 学会利用其原理求解最大团问题实验原理问题描述:给定无向连通图 G =(V,E) ,其中 V 是非空集合,称为顶点集;E 是 V 中元素构成的无序二元组的集合,称为边集,无向图中的边均是顶点的无序对,无序对常用圆括号“() ”表示,如果 UV,且对任意两个顶点 u,vU 有(u,v) E,则称 U 是 G 的完全子图, G 的完全子图是 G 的团当前仅当 U 不包含在 G 的更大的完全子图中。 G 的最大团是指 G 中
2、所含顶点数最多的团。由上图来看, (1,2,4)中每个顶点之间都相连接,并且都包含在图 G 中,所以(1,2,4)是一个图 G 的一个团,但是( 1,2,3,4)由于(1,3)之间没有连线,所以没有保证所有顶点都连接,因此不是团,而(1,2,3) (1,5,4 ) (2,3,4)都是三顶点的团,而该图包含顶点数最多的团就是三个,因此(1,2,3) (1,5,4 )(2,3,4)属于最大团,最大团问题就是求解这样的问题。程序中采用了一个比较简单的剪枝策略,即如果剩余未考虑的顶点数加上团中顶点数不大于当前解的顶点数,可停止继续深度搜索,否则继续深度递归当搜索到一个叶结点时,即可停止搜索,此时更新最
3、优解和最优值。基本解题步骤:(1) 针对所给问题,定义问题的解空间;(2) 确定易于搜索的解空间结构;(3) 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。1 2345实验步骤(1 )首先设最大团为一个空团,往其中加入一个顶点;(2 )然后依次考虑每个顶点,查看该顶点加入团之后仍然构成一个团,如果可以,考虑将该顶点加入团或者舍弃两种情况,如果不行,直接舍弃,然后递归判断下一顶点;(3 )可采用剪枝策略来避免无效搜索;(4 )为了判断当前顶点加入团之后是否仍是一个团,只需要考虑该顶点和团中顶点是否都有连接。关键代码void Clique:Backtrack(int i) /计算
4、最大团if(in) /到达叶子节点 for(int j=1;j=bestn) /修改一下上界函数的条件,可以得到 xi=0; /相同点数时的解 Backtrack(i+1); 测试结果当输入图如下时:当输入图如下时:1 23451 2345当输入图如下时:1 2345附录:完整代码(回溯法)/最大团问题 回溯法求解#includeusing namespace std;class Cliquefriend void MaxClique(int *,int *,int );private:void Backtrack(int i);int *a; /图的邻接矩阵int n; /图的顶点数int
5、*x; /当前解int *bestx; /当前最优解int cn; /当前顶点数int bestn; /当前最大顶点数 ;void Clique:Backtrack(int i) /计算最大团if(in) /到达叶子节点 for(int j=1;j=bestn) /修改一下上界函数的条件,可以得到 xi=0; /相同点数时的解 Backtrack(i+1); void MaxClique(int *a,int *v,int n) /初始化YClique Y;Y.x=new intn+1;Y.a=a;Y.n=n;Y.cn=0;Y.bestn=0;Y.bestx=v;Y.Backtrack(1);delete Y.x;coutn;/int an+1n+1; /由于定义的是int *a,且采用的是二维数组传参,因此 int *a=new int *n+1; /两种解决方法,一是给定第二维的大小,二是通过 for(int i=0;iedge;coutvw;avw=1;awv=1; int *p=new intn+1;MaxClique(a,p,n);system(“pause“);return 0;