回溯法 -----n后问题

Class Queen{ private: bool Place(int k); void Backtrack(int t); int n, //皇后个个数 *x; // 当前解 long sum; //当前已找到的可行方案 }; bool Queen::Place(int k) { for(int j=1;j <k; j++) if((abs(k-j) == abs(x[j]-x[k]))||(x[j]==x[k])) return false; return ture; } void Queen::Backtrak(int t) { if(t>n) sum++; else for(int i=1; i <= n; i++) { x[t] =i; if(Place(t))Backtrak(t+1); } } n后问题

 

1.问题描述

 

   在n*n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规矩,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n*n格的棋盘上方置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。

 

2.算法设计

 

   用n元组x[1;n]表示n后问题的解。其中,x[i]表示皇后i放置在棋盘的第i行的第x[i]列。由于不容许将2个皇后放在同一列上,所以解向量中的x[i]互不相同。2个皇后不能放在同一斜线上是问题的隐约束。对于一般的n后问题,这一隐约束条件可以化成显约束的形式。如果将n*n 格的棋盘看做二维方阵,其行号从上到下,列号从左到右依次编号为1,2,…n。从棋盘左上角到右下角的主对角线及其平行线(即斜率为-1的各斜线)上,2个下标值的差(行号-列号)值相等。同理,斜率为+1的每条斜线上,2个下标值的和(行号+列号)值相等。因此,若2个皇后放置的位置分别是(i,j)和(k,l),且 i-j = k -l 或 i+j = k+l,则说明这2个皇后处于同一斜线上。以上2个方程分别等价于i-k = j-l 和 i-k =l-j。由此可知,只要|i-k|=|l-j|成立,就表明2个皇后位于同一条斜线上。

    用回溯法解n后问题,用完全n叉树表示解空间。可行性约束Place剪去不满足行,列和斜线约束的子树。

    下面的解n后问题的回溯法中,递归函数Backtrack(1)实现对整个解空间的回溯搜索。Backtrack(i)搜索解空间中第i层子树。类Queen的数据成员记录解空间中节点信息,以减少传给Backtrack的参数。sum记录当前已找到的可行方案数。

    在算法Backtrack中,当i>n是,算法搜索至叶节点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案数sum增1。

    当i<=n时,当前扩展节点Z是解空间中的内部节点。该节点有x[i]=1,2,..,n共n个儿子节点。对当前扩展节点Z的每一个儿子节点,由Place检查其可行性,并以深度优先的方式递归对可行子树搜索,或剪去不可行子树。

 

 

 

———————————————————

 

    原文作者:回溯法
    原文地址: https://blog.csdn.net/tjsinor2008/article/details/5603878
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞