八皇后算法

我们提供一种遍历的思路,我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的位置,接着就到下一行或列遍历下一个棋子的合适位置,这种遍历思路可以保证我们遍历过程中有一个条件是绝对符合的——就是下一个棋子的摆放位置与前面的棋子不在同一行(或列)。接下来,我们只要判断当前位置是否还符合其他条件,如果符合,就遍历下一行(或列)所有位置,看看是否继续有符合条件的位置,以此类推,如果某一个行(或列)的所有位置都不合适,就返回上一行(或列)继续该行(或列)的其他位置遍历,当我们顺利遍历到最后一行(或列),且有符合条件的位置时,就是一个可行的8皇后摆放方案,累加一次八皇后可行方案的个数,然后继续遍历该行其他位置是否有合适的,如果没有,则返回上一行,遍历该行其他位置,依此下去。这样一个过程下来,我们就可以得出所有符合条件的8皇后摆放方案了。这是一个深度优先遍历的过程,同时也是经典的递归思路。


下面用循环实现

public class EightQueensCirculation {

    private static final boolean AVAILABLE = true;
    private int squares = 8, norm = squares - 1;
    private int positionInRow[] = new int[squares];
    private int p = -1;
    private boolean[] rows = new boolean[squares];
    private boolean[] column = new boolean[squares];
    private boolean[] leftDiagonal = new boolean[2 * squares - 1];
    private boolean[] rightDiagonal = new boolean[2 * squares - 1];
    private static int howMany = 0;

    public EightQueensCirculation() {
        // To complete the initialization work for the
        // column,leftDiagonal,rigthDiagonal.
        for (int i = 0; i < squares; i++) {
            rows[i] = AVAILABLE;
            column[i] = AVAILABLE;
            positionInRow[i] = -1;
        }
        
        for (int i = 0; i < 2 * squares - 1; i++) {
            leftDiagonal[i] = AVAILABLE;
            rightDiagonal[i] = AVAILABLE;
        }
    }

    public void printResults(int[] columns) {
        int row, col;
        System.out.println("八皇后问题的第 " + howMany + " 种解法");
        System.out.print("八皇后问题的结果为:");
        for (int e : columns) {
            System.out.print(e);
        }
        System.out.println("\n具体的图示如下图所示:");
        for (row = 0; row < squares; row++) {
            for (col = 0; col < squares; col++) {
                if (col == positionInRow[row]) {
                    System.out.print("@");
                } else {
                    System.out.print("*");
                }
            }
            System.out.println();
        }
        System.out.println();
    }

    public void putQueen() {
        int row = 0, col;
        while (true) {
            for (col = p + 1; col < squares; col++) {
                if (rows[row] == AVAILABLE && column[col] == AVAILABLE && leftDiagonal[row + col] == AVAILABLE && rightDiagonal[row - col + norm] == AVAILABLE) {
                    break;
                }
            }
            //在当前的行里面找到了可以放置皇后的位置
            if (col < squares) {
                rows[row] = !AVAILABLE;
                column[col] = !AVAILABLE;
                leftDiagonal[row + col] = !AVAILABLE;
                rightDiagonal[row - col + norm] = !AVAILABLE;
                positionInRow[row] = col;
                p = col;
            } else if (row > 0) {//如果当前行没办反放置皇后了,那么回溯到前一行
                row--;
                p = positionInRow[row];
                rows[row] = AVAILABLE;
                column[p] = AVAILABLE;
                leftDiagonal[row + p] = AVAILABLE;
                rightDiagonal[row - p + norm] = AVAILABLE;
                positionInRow[row] = -1;
                continue;
            } else {
                break;
            }
            
            if (row == squares - 1) {
                howMany += 1;
                printResults(positionInRow);
                p = positionInRow[row];
                rows[row] = AVAILABLE;
                column[p] = AVAILABLE;
                leftDiagonal[row + p] = AVAILABLE;
                rightDiagonal[row - p + norm] = AVAILABLE;
                positionInRow[row] = -1;
                continue;
            } else {
                row++;
                p = -1;
                continue;
            }
        }
    }

    public static void main(String args[]) {
        EightQueensCirculation eightQueens = new EightQueensCirculation();
        eightQueens.putQueen();
        System.out.println("皇后问题一共有" + howMany + "种解法");
    }
}

下面用递归实现

public class EightQueensRecursive {
        
    private static final boolean AVAILABLE = true;
    private int squares = 8, norm = squares-1;
    private int positionInRow[] = new int[squares];
    private boolean[] column = new boolean[squares];
    private boolean[] leftDiagonal = new boolean[2*squares-1];
    private boolean[] rightDiagonal = new boolean[2*squares-1];
    private static int howMany = 0;

    public EightQueensRecursive() {
        //To complete the initialization work for the column,leftDiagonal,rigthDiagonal.
        for(int i=0; i<squares; i++){
            column[i] = AVAILABLE;
            positionInRow[i] = -1;
        }

        for(int i=0; i<2*squares-1; i++){
            leftDiagonal[i] = AVAILABLE;
            rightDiagonal[i] = AVAILABLE;
        }
    }

    public void printResults(int[] columns) {
        int row,col;
        System.out.println("八皇后问题的第 "+howMany+" 种解法");
        System.out.print("八皇后问题的结果为:");
        for(int e:columns) {
            System.out.print(e);
        }
        System.out.println("\n具体的图示如下图所示:");
        for(row=0; row<squares; row++) {
            for(col=0; col<squares; col++) {
                if(col == positionInRow[row]) {
                    System.out.print("@");
                } else {
                    System.out.print("*");
                }
            }
            System.out.println();
        }
        System.out.println();
    }

    public void putQueen(int row) {
        //如果前面已经得到了一个可行解
        for(int i=0; i<squares; i++) {
            if(row>squares-1) break;
            if(column[i] == AVAILABLE && leftDiagonal[row+i] == AVAILABLE && rightDiagonal[row-i+norm] == AVAILABLE) {
                positionInRow[row] = i;
                column[i] = !AVAILABLE;
                leftDiagonal[row+i] = !AVAILABLE;
                rightDiagonal[row-i+norm] = !AVAILABLE;
                if(row < squares-1) {
                    putQueen(row+1);
                } else {
                    howMany += 1;
                    printResults(positionInRow);
                }
                column[i] = AVAILABLE;
                leftDiagonal[row+i] = AVAILABLE;
                rightDiagonal[row-i+norm] = AVAILABLE;
            }
        }
    }

    public static void main(String args[]) {
        EightQueensRecursive eightQueens = new EightQueensRecursive();
        eightQueens.putQueen(0);
        System.out.println("皇后问题一共找到了 "+howMany+"组解。");
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值