1、题目描述:在8x8的国际象棋上面摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行,同一列或者同一条斜线上,请问有多少种摆法?

当时高斯先生计算说有76种,但是最后有92种。

2、代码解析(递归) 

步骤:分解为两个子问题,首先在第一行放置一个棋子,第二在其他安全的不被攻击的地方放第二个棋子,以此类推。

结束条件:放完第八个棋子就结束了。

package com.yuanfeng.test;/**
 * Created by yuanfeng on 2019/7/17 10:12
 */

/**
 *@ClassName EightQueen
 *@Description T0D0
 *@Author yuanfeng
 *@Date 2019/7/17 10:12
 *@Version 1.0
 **/
public class EightQueen {

    //定义一个变量计算种数
    private static int count = 0;

    /*
    *
     * @Author yuanfeng
     * @Description //TODO
     * @Date 10:32 2019/7/17
     * @Param [row, j, chess]chess传进来的棋盘
     * @return int
     **/
    public static int security(int row,int j,int[][]chess){

        int i = 0,flag1 = 0,flag2= 0,flag3=0,flag4=0,flag5=0,k;
        //判断列方向的危险
        for(i = 0;i<8;i++){
            if(chess[i][j] != 0){
                flag1 = 1;
                break;
            }
        }
        //判断左上方,因为代码不好直接判断啊一条斜线
        for (i = row,k = j;i>=0 && k>=0;i--,k--){
            if(chess[i][k] != 0){
                flag2 = 1;
                break;
            }
        }
        //判右下方,因为代码不好直接判断啊一条斜线
        for (i = row,k = j;i<8 && k<8;i++,k++){
            if(chess[i][k] != 0){
                flag3 = 1;
                break;
            }
        }


        //判断右上方,因为代码不好直接判断啊一条斜线
        for (i = row,k = j;i>=0 && k<8;i--,k++){
            if(chess[i][k] != 0){
                flag4 = 1;
                break;
            }
        }
        //判断左下方,因为代码不好直接判断啊一条斜线
        for (i = row,k = j;i<8 && k>=0;i++,k--){
            if(chess[i][k] != 0){
                flag5 = 1;
                break;
            }
        }

        if(flag1 == 1 || flag2 == 1 || flag3 == 1 || flag4 == 1 || flag5 == 1){
            return 0;
        }else {
            return 1;
        }


    }
    /*
    *
     * @Author yuanfeng
     * @Description //TODO
     * @Date 10:22 2019/7/17
     * @Param [row, col, chess]chess代表指向每一行的指针
     * @return void
     **/
    //参数为row,col,指向棋盘的引用


    public static void eightQueen(int row,int col,int[][] chess){

        //建立一个临时棋盘来存放最后要打印的92个棋盘
        int[][] chess2 = new int[8][8];
        int i,j;
        //主棋盘赋值给临时的棋盘
        for( i = 0;i < chess2.length;i++){

            for (j = 0;j < chess2[0].length;j++) {

                chess2[i][j] = chess[i][j];
                }
        }

        //递归结束条件,row==8已经到了第九行了,代表前面已经结束了
        if(row == 8){
            count=count+1;
            System.out.println("第"+count+"种");
            for(i = 0;i<8;i++){
                for( j = 0;j<8;j++){
                    System.out.print(chess2[i][j]);
                }
                System.out.println();//换行
            }
            System.out.println();
        }else {

            //不符合条件的时候,判断这个位置是否有攻击危险
            //如果没有危险。继续往下
            //每一行一格一格往下判断

            for(j = 0;j<col;j++){
                //判断是否危险
                if(security(row,j,chess) == 1){

                    for(i = 0;i<8;i++){
                        chess2[row][i] = 0;//整行所有列的值赋值为0
                    }
                    chess2[row][j] = 1;//不危险的j的位置赋值为1
                    //接着下一行递归测试
                    eightQueen(row+1,col,chess2);
                }
            }
        }
    }
    public static void main(String[] args) {

        //定义一个二维数组来表示8x8的棋盘
        int chess[][] = new int[8][8];

        //棋牌所有初始化为0
        for(int i = 0;i < chess.length;i++){
            for (int j = 0;j < chess[0].length;j++){
                chess[i][j] = 0;
            }
        }

        eightQueen(0,8,chess);
        System.out.println("总共有"+count+"种解决方法");
    }

}

 

总结:

说说大体的思路,本身这个题目中我们首先将一个二维数组棋盘赋值为0,目的是最后1是代表的皇后。

递归进入eightQueen()的时候,最开始row是不满足row == 8这个条件的,所以这个时候进行else判断,定义一个security方法判断row行j列的元素是否安全,整行赋值0,安全的位置赋值1,row+1进行下一行的递归。

其中security这个方法是判断该皇后位置的左上方,右下方,左下方,右上方的位置是否存在冲突。