码迷,mamicode.com
首页 > 其他好文 > 详细

八皇后问题

时间:2014-09-26 00:50:47      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   java   ar   strong   for   

http://blog.csdn.net/baple/article/details/7181404

8皇后问题是一道非常经典的题目。题目是说,一个N*N的国际象棋棋盘上主放置N个皇后,使其不能相互攻击,即任何两个皇后都不能处在棋盘的同一行,同一列,同一条斜线上,试问共有多少种摆法?

        其实,题目就是要找出所有的可能情况,然后排除其中不符合条件的情况,剩下的情况即为所要求的。怎么找出所有的情况呢?对于8皇后,我们可以使用穷举法, 穷举出每一种放置方法,然后判断是否符合题意。如果每次放一行,那就需要8重循环才可以解出来。虽然空间复杂度可以小到为0,但是时间复杂度太高。

        书中一般使用回溯法来解此题。仔细分析此题,可以发现:每一行上只能放置一个皇后,然后后面每行放置的皇后,不能与前面的行上放置的皇后在同一列上或者同 一对角线上。所以用一个一维数组就可以存放在棋盘上放置的皇后的行列信息:一维数组的第i个位置存放的数值j就表示,在棋盘的第i行、第j列上放着一个皇 后。棋盘的一行就用一个元素来表示,所以不能在同一行就不用判断了。知道了皇后在棋盘的行列位置后,判断是否符合后面的两个条件也比较容易了(对角线只要 仔细分析下,两个二维坐标点如果在对角线上,他们的行列坐标将会满足何种情况即可)。

         搞定了数据结构,接着就要考虑如何进行回溯搜索了。回溯一般借用递归来实现。用我的一个ACM非常牛的一个同学的话来说:回溯就是让计算机自动的去搜索, 碰到符合的情况就结束或者保存起来,在一条路径上走到尽头也不能找出解,就回到原来的岔路口,选择一条以前没有走过的路继续探测,直到找到解或者走完所有 路径为止。就这一点,回溯和所谓的DFS(深度优先搜索)是一样的。那现在的关键是,怎么实现搜索呢?回溯既然一般使用递归来实现,那个这个递归调用该如 何来写呢?我现在的理解就是,进行回溯搜索都会有一系列的步骤,每一步都会进行一些查找。而每一步的情况除了输入会不一样之外,其他的情况都是一致的。这 就刚好满足了递归调用的需求。通过把递归结束的条件设置到搜索的最后一步,就可以借用递归的特性来回溯了因为合法的 递归调用总是要回到它的上一层调用的,那么在回溯搜索中,回到上一层调用就是回到了前一个步骤。当在当前步骤找不到一种符合条件情况时,那么后续情况也就 不用考虑了,所以就让递归调用返回上一层(也就是回到前一个步骤)找一个以前没有尝试过的情况继续进行。当然有时候为了能够正常的进行继续搜索,需要恢复 以前的调用环境。

Java现实:

 1 public class EightQueen {
 2 
 3     public static final int SIZE = 8;
 4     public static int[] queens = new int[SIZE];
 5     public static int sum = 0;
 6     
 7     /* 检查是否有冲突 */
 8     public static boolean isValid(int row, int column){
 9         for(int i=1; i <= row; i++){
10             if (queens[row-i] == column//是否在同一列有冲突
11                     || queens[row-i] == column - i//左上角是否冲突
12                     || queens[row-i] == column + i) {//右上角是否冲突
13                 return false;
14             }
15         }
16         return true;
17     }
18     
19     public static boolean search(int row){
20         if(row == SIZE){
21             for(int i = 0; i < queens.length;i++){
22                 System.out.print(queens[i] + " ");
23             }
24             System.out.println();
25             sum++;
26             return false;//表示已经放完所有的行
27             //return true  如果返回true是尝试一次成功,程序就结束
28         }
29         
30         /* 在某一行尝试所有的列*/
31         for(int column = 0; column < SIZE; column++){
32             queens[row] = column;
33             /* 如果某一行的放置与前面的列不冲突,进行下一行的尝试*/
34             if (isValid(row, column) && search(row+1)) {
35                 /* 用于确认上一行的放置是正确的 */
36                 return true;
37             }
38         }
39         /* 如果在某一行所有的尝试都失败则返回false, 则上一行的尝试也失败,修改上一行的放置*/
40         return false;
41     }
42     
43     public static void main(String[] args) {
44         search(0);
45         System.out.println("共有"+sum+"放置方法");
46     }
47 }

 

八皇后问题

标签:style   blog   http   color   使用   java   ar   strong   for   

原文地址:http://www.cnblogs.com/wanghui390/p/3993798.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!