logo资料库

用回溯法解决N色方柱.doc

第1页 / 共7页
第2页 / 共7页
第3页 / 共7页
第4页 / 共7页
第5页 / 共7页
第6页 / 共7页
第7页 / 共7页
资料共7页,全文预览结束
中国传媒大学 2011 学年第 一 学期 计算机算法设计与分析 课程 计算机算法设计与分析 题 目回溯法解决 n 色方柱问题的算法设计与分析 学生姓名 学 班 学 号 级 院 任课教师 1
回溯法解决 n 色方柱问题的算法设计与分析 摘要: 对于计算机科学来说,算法(Algorithm)的概念是至关重要的。算法是一 系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获 得所要求的输出。为了充分理解算法分析的思想,利用算法思想解决实际问题, 所以用回溯法解决书上 P181 习题 5—7 n 色方柱问题。 关键字: 计算机算法 回溯法 n 色方柱 回溯法背景: 回溯法也称为试探法,该方法首先暂时放弃关于问题规模大小的限制,并 将问题的候选解按某种顺序逐一枚举和检验。当发现当前候选解不可能是解时, 就选择下一个候选解;倘若当前候选解除了还不满足问题规模要求外,满足所有 其他要求时,继续扩大当前候选解的规模,并继续试探。如果当前候选解满足包 括问题规模在内的所有要求时,该候选解就是问题的一个解。在回溯法中,放弃 当前候选解,寻找下一个候选解的过程称为回溯。扩大当前候选解的规模,以继 续试探的过程称为向前试探。 回溯法的基本思想:确定了解空间的组织结构后,回溯法就从开始结点(根 结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结 点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一 个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当 前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。换句话 说,这个结点不再是一个活结点。此时,应往回移动(回溯)至最近的一个活结 点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在 解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。 1、问题描述: 设有 n 立方体,每个立方体的每个面用红、黄、蓝、绿等 n 种颜色之一染色。 要把这 n 个立方体叠成一个方形柱体,使得柱体的 4 个侧面的每一侧均有 n 种不 同的颜色。试设计一个回溯算法,计算出 n 个立方体的一种满足要求的叠置方案。 例如:第一行有 1 个正整数 n,0
上图中 F 表示前面,B 表示背面,L 表示左面,R 表示右面,T 表示顶面,D 表示 底面。相应的 2 表示前面,3 表示背面,0 表示左面,1 表示右面,5 表示顶面, 4 表示底面。 2、算法分析: 此问题中,立方体的每对相对的面得颜色是要考察的关键因素。将每个立方 体表示为有 n 个顶点的图。图中每个顶点表示一种颜色。在立方体每对向对面的 顶点建连一条边。例如,图(b)是图(a)所示的 4 个立方体所相应的子图。 3
将上述子图合并,并标明每一条边来自哪一个立方体如图 2 所示。 下一步在构成的图中,找出 2 个特殊子图。一个子图表示叠置的 n 哥立方体 的前侧面与背侧面,另一子图表示叠置的 n 个立方体的左侧面与右侧面。这两个 子图应满足下述性质。 2 个子图没有公共边。 1 每个子图有 n 条边,且每个立方体恰好一条边。 2 3 子图中每个顶点的度均为 2。 对于图 2 中的图,找出满足要求的两个子图如图 3 所示。 给子图的每条边一个方向,使每个顶点有一条出边和一条入边。有向边得始 点对应于 面和左面;有向边的终点对应于背面和右面。图 3 给出的满足要求的解如下。 Cube1 Cube2 Cube3 Cube4 0(L) Y G B R 1(R) B Y R G 2(F) G R B Y 3(B) R B Y G 上述算法的关键是找满足性质(1)、(2)和(3)的子图。用回溯法。 3、实验数据与结果: 实验输入文件: input . txt 4 RGBBY 0 2 1 3 0 0 3 0 2 1 0 1 2 1 0 2 1 3 1 3 3 0 2 2 实验输出结果: output . txt RBGYRR YRBGRG BGRBGY GYYRBB 参考文献: 王晓东.计算机算法设计与分析(第3版) 电子工业出版社 附录: 二维数组 board[n][6]存储 n 个立方体各面的颜色,solu[n][6]存储解 ------------------------------------------------------------------------------------------------------- void search() { int i,t,cube,newg,over,ok; 4
int *vert=new int[n]; int *edge=new int[n*2]; for(i=0;i-2){ //每个立方体找 2 次 t++; cube=t%n; if(newg)edge[t]=-1; over=0;ok=0; while(!ok && !over){ edge[t]++; if(edge[t]>2)over=1; else ok=(t2+t/n*2)ok=0; if(++vert[board[cube][edge[t]*2+1]]>2+t/n*2)ok=0; if(t%n==n-1&&ok) //check that each vertex is order 2 for(i=0;i2+t/n*2)ok=0; if(ok){if(t==n*2-1){ //找到解 ans++; out(edge); return; } else newg=1; } else{ //ok //取下一条边 --vert[board[cube][edge[t]*2]]; --vert[board[cube][edge[t]*2+1]]; t--;newg=0; } //over } else{ //回溯 t--; if(t>-1){ cube=t%n; --vert[board[cube][edge[t]*2]]; --vert[board[cube][edge[t]*2+1]]; } t--;newg=0; } } } -------------------------------------------- 5
找到一个解由 out 输出。 -------------------------------------------- void out(int edge[]) { int k,a,b,c,d; for(int i=0;i<2;i++){ for(int j=0;j
{ readin(); search(); if(ans==0)cout<<"No Solution!"<>n; Make2DArray(board,n,6); Make2DArray(solu,n,6); color=new char[n]; used=new int[n]; for(int j=0;j>color[j]; for(int i=0;i>board[i][j]; } 7
分享到:
收藏