- 1、本文档共19页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
递归与回溯 八皇后问题分析 【背景】八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。 八皇后的两组解 设八个皇后为xi,分别在第i行 i 1,2,3,4……,8 ;问题的解状态:可以用 1,x1 , 2,x2 ,……, 8,x8 表示8个皇后的位置;由于行号固定,可简单记为: x1,x2,x3,x4,x5,x6,x7,x8 ;问题的解空间: x1,x2,x3,x4,x5,x6,x7,x8 ,1≤xi≤8 i 1,2,3,4……,8 ,共88个状态;约束条件:八个 1,x1 , 2,x2 , 3,x3 , 4,x4 , 5,x5 , 6,x6 , 7,x7 , 8,x8 不在同一行、同一列和同一对角线上。原问题即:在解空间中寻找符合约束条件的解状态。 【问题分析】 1.按什么顺序去查找所有的解 a.盲目的枚举算法 void main int x[100]; for x[1] 1;x[1] 10;x[1]++ for x[2] 1;x[2] 10;x[2]++ for x[3] 1;x[3] 10;x[3]++ for x[4] 1;x[4] 10;x[4]++ for x[5] 1;x[5] 10;x[5]++ for x[6] 1;x[6] 10;x[6]++ for x[7] 1;x[7] 10;x[7]++ for x[8] 1;x[8] 10;x[8]++ if check x 0 printf x ; 该如何解决冲突的问题呢? 1.行;我们是按照行枚举的,保证了一行一个皇后; 2.列:判断是否存在x[i] x[j] 3.对角线:主对角线的i-j与从对角线的i+j存在特殊关系,如图: 如果能够排除那些没有前途的状态,会节约时间; 如何提前发现? 回溯法指导思想——走不通,就掉头 如 1,1, x3,x4,x5,x6,x7,x8 没有必要再扩展; 这种状态扩展后会产生86个结点; 同样的 1,2, x3,x4,x5,x6,x7,x8 ,………也应被排除。 在每一次扩展E结点后,都进行检查; 对检查结果如何处理? 检查合格的才继续向下扩展; 遇到不合格的“掉头就走”。 只要当前枚举到的状态可行,就继续枚举下去。当找到一种方案或者无法继续枚举下去时,就退回到上一状态。退回到上一状态的过程叫做回溯,枚举下一个状态的过程叫做递归。 回溯就是像人走迷宫一样,先选择一个前进方向尝试,一步步试探,在遇到死胡同不能再往前的时候就会退到上一个分支点,另选一个方向尝试,而在前进和回撤的路上都设置一些标记,以便能够正确返回,直到达到目标或者所有的可行方案都已经尝试完为止。 回溯算法用伪代码描述如下: Void search 当前状态 Begin If 当前状态等于目标状态 then exit; for 对所有可能的新状态 do search 新状态 ; End; 考虑八皇后问题? 我们可以依次确定每一行皇后的位置 如果在某一列可以放下一个皇后,我们就在这里放下,并搜索下一行 若无法放下皇后则回到上一行,即回溯 当n行的皇后都已确定后,我们就找到了一种方案 算法基本框架 Void Try int i ; 搜索第i行皇后的位置 Begin int j; if i n+1 then 输出方案并回溯; for j: 1 to n do if 皇后能放在第i行第j列的位置 then begin 放置第i个皇后; 对放置皇后的位置进行标记; Try(i+1) 对放置皇后的位置释放标记; end; end; 如何判断某行某列能否放皇后? 该行能否放? 按行搜索,保证每一行放一个皇后 用数组标记某列能否放 该列能否放? 对角线能否放? 对角线上的点和或差相同,也可用数组标记 问题已解决! 用a数组标记某列能否放 用b数组标记左下到右上的对角线能否放 用c数组标记右下到左上的对角线能否放 【代码】 #include int a[10] 0 ,b[20] 0 ,c[20] 0 ,f[9][9] 0 ,k;//a,b,c标记数组; k记录解的数量 void deal int n //搜索第n行 int i,j; if n 9 //已经把前八行搜索完毕,没有冲突,是一种满足条件的解 k++; printf %d: \n,k ; //输出第K组解 for i 1;i 8;i++ for j 1;j 8;j++ printf %d,f[i][j
您可能关注的文档
最近下载
- 丽声北极星自然拼读绘本第一级 Lola and the King 课件.pptx
- 人教版2024-2025学年九年级数学上册10月月考试题[含答案].pdf
- 品质工程教学课件.pptx
- 鲁教版五四制初一年级上册册数学知识点.pdf VIP
- 《聪明的牧羊人——欧洲民间故事精选》名著导读课件.pptx VIP
- QBT 2578-2002 陶瓷原料化学成分光度分析方法.docx VIP
- 《葡萄酒葡萄酒》课件.pptx VIP
- 新人教版高中数学选择性必修第一册全套教案含情景引入核心素养word版.docx VIP
- you and me(君と僕) 松井佑贵 吉他指弹 吉他谱.pdf
- 非急救转运协议书模板.docx
文档评论(0)