八皇后问题概要.pptVIP

  • 4
  • 0
  • 约2.9千字
  • 约 19页
  • 2016-12-02 发布于湖北
  • 举报
递归与回溯 八皇后问题分析 【背景】 八皇后问题是一个以国际象棋为背景的问题:如何能够在 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; 如何判断某行某列能否放皇后? 该行能否放? 按行搜索,保证每一行放一个皇后 用数组标记某列能否放 该列能否放? 对角线能否放? 对角线上的点和或差相同,也可用数

文档评论(0)

1亿VIP精品文档

相关文档