java编程题——八皇后问题

背景及问题介绍:

八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。

java编程题——八皇后问题_第1张图片

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。

解决方法:创建一个8x8二维数组解决或者一个一维数组解决,对于一维数组arr,用下标i表示行数,对应的arr[i]表示列数。

总体步骤:

步骤一:先在第一行的第一个位置放置皇后

步骤二:确定好第一行的皇后之后,从第二行的第一个到第八个位置,挨个判断,如果满足条件,确定好一个皇后,再去找第三行,如果八个位置都不满足情况,那么就回到第一行,把皇后放置第二个位置,又继续看第二行。

步骤三:直到第八行,八个位置挨个判断,如果符合条件,就直接打印数组,当第八行都判断完之后,将第八行回到第七行,从之前的皇后的下一个位置开始判断,满足条件,又去看第八行。当第七行所有位置都判断完之后,回溯上第六行,以此类推,直到把第一行八个位置轮完。

要实现在这个递归和回溯的功能,可用以下代码实现:

二维数组

class BHH {
    public void game(int board[][], int row) {//row记录行数,row = 0
        //遍历一行中的每一列
        for (int i = 0; i < 8; i++) {
            if (checkBoard(board, row, i))//检测该位置是否正确,row,i为该位置的行数和列数
            {
                board[row][i] = 1;//将该位置设置为皇后
                if (row == 7) {
                    print(board);//直到在第八行能找到满足要求的位置才打印
                } else {
                    game(board, row + 1);
                }
            }
            board[row][i] = 0;//将皇后设置为0,防止干扰打印下一个棋盘的结果
        }
    }

 一维数组:

class BHH {
    private int n = 0;//记录结果个数
    public void game(int board[], int row) {//row记录行数,row = 0
        //遍历一行中的每一列
        for (int i = 0; i < 8; i++) {
            board[row] = i;//将该位置设置为皇后
            if (checkBoard(board, row, board[row])) {//检测该位置是否正确,row,board[row]为该位置的行数和列数
                if (row == 7) {
                    print(board,n);
                } else
                    game(board, row + 1);
            }
            //board[row] = 0;一维数组是不需要这一步的,当循环下一次时,board[row] = i会覆盖上一次的结果
        }
    }

     而检测每一个要放置的皇后位置是否合理。对于这一步骤,检测是否同列就不用说了,对于检测即将放置的皇后的左上和右上是否有皇后,我们把行列看成x,y轴(谁是x谁是y无所谓),这相当于看有没有和这个皇后构成斜率为1的直线,也就是对于两个皇后q1(x1,y1), q2(x2,y2),看(x1-x2)的绝对值和(y1-y2)的绝对值是否相等,用以下代码实现:

二维数组:

if(Math.abs(Math.abs(row-i) - Math.abs(col - j)) < 0.001  && board[i][j] == 1){
 	return false;
}

一维数组:

if (Math.abs(Math.abs(row - i) - Math.abs(board[row] - board[i])) < 0.001){
    return false;
}

二维数组的最终代码:

public class SdgStu {
    public static void main(String[] args) {
        int board[][] = new int[8][8];//定义一个8*8的棋盘
        BHH bhh = new BHH();
        bhh.game(board, 0);
    }
}

class BHH {
    private int n = 0;//记录结果个数
    public void game(int board[][], int row) {//row记录行数
        //遍历一行中的每一列
        for (int i = 0; i < 8; i++) {
            if (checkBoard(board, row, i))//检测该位置是否正确,row,i为该位置的行数和列数
            {
                board[row][i] = 1;//将该位置设置为皇后
                if (row == 7) {
                    print(board,n);//直到在第八行能找到满足要求的位置才打印
                } else {
                    game(board, row + 1);
                }
            }
            board[row][i] = 0;//将皇后设置为0,防止干扰打印下一个棋盘的结果
        }
    }

    //检查在该位置放置皇后是否正确
    public boolean checkBoard(int board[][], int row, int col) {
        //判断是否有同列的皇后
        for (int i = 0; i < row; i++) {
            if (board[i][col] == 1) {
                return false;
            }
        }

        //之前有row个皇后,遍历前row行
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < 8; j++) {
                //判断该位置的左上和右上是否有皇后
                if (Math.abs(Math.abs(row - i) - Math.abs(col - j)) < 0.001 && board[i][j] == 1) {
                    return false;
                }
            }
        }
        return true;
    }

    //打印结果
    public void print(int board[][],int count) {
        this.n = ++count;
        System.out.println("第" + count + "个结果:");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.print("\n");//换行
        }
        System.out.println();//空一行
    }
}

一维数组的最终代码:

public class test {
    public static void main(String[] args) {
        int board[] = new int[8];
        BHH bhh = new BHH();
        bhh.game(board, 0);
    }
}

class BHH {
    private int n = 0;//记录结果个数
    public void game(int board[], int row) {//row记录行数
        //遍历一行中的每一列
        for (int i = 0; i < 8; i++) {
            board[row] = i;//将该位置设置为皇后
            if (checkBoard(board, row, board[row])) {//检测该位置是否正确,row,board[row]为该位置的行数和列数
                if (row == 7) {
                    print(board,n);
                } else
                    game(board, row + 1);
            }
            //board[row] = 0;一维数组是不需要这一步的,当循环下一次时,board[row] = i会覆盖上一次的结果
        }
    }

    public boolean checkBoard(int board[], int row, int col) {
        for (int i = 0; i < row; i++) {
            //判断是否同列
            if (board[i] == col) {
                return false;
            }
            //判断是否在左上和右上
            if (Math.abs(Math.abs(row - i) - Math.abs(board[row] - board[i])) < 0.001){
                return false;
            }
        }
        return true;
    }

    //打印
    public void print(int board[],int count){
        this.n = ++count;
        System.out.println("第" + count + "个结果:");
        for(int i = 0; i < board.length; i++){
            System.out.print(board[i] + " ");
        }
        System.out.println();//换行
    }
}

运行结果:

java编程题——八皇后问题_第2张图片

 

 java编程题——八皇后问题_第3张图片

你可能感兴趣的:(java,算法,排序算法,数据结构)