易理解java代码8皇后问题

时间:2021-05-17 14:38:40

马上就要蓝桥杯比赛了,我这些算法还是不会,确实有点慌,今天一天早上睡到很晚不愿起床,然后才开始研究8皇后问题。这也是典型的回溯与递归问题。其实本质上和马踏棋盘问题非常类似,八皇后问题呢,就是要判断主对角线,副对角线,横排和竖排不能有皇后。这个是这个问题的着重点。先来看下八皇后问题吧。

1.问题描述:

    在8*8的棋盘中放8个皇后,使得每个皇后不能放在同一行,同一列,同一主对角线上(左下斜),同一副对角线上(右上斜)。

2.输入: 无(当然也可以优化求任意皇后,这个就不是重点了)

3.输出示例:

      1  *  *  *  *  *  *  *
      *  *  *  *  2  *  *  *
      *  *  *  *  *  *  *  3
      *  *  *  *  *  4  *  *
      *  *  5  *  *  *  *  *
      *  *  *  *  *  *  6  *
      *  7  *  *  *  *  *  *
      *  *  *  8  *  *  *  *

    ===============

    1  *  *  *  *  *  *  *
      *  *  *  *  *  2  *  *
      *  *  *  *  *  *  *  3
      *  *  4  *  *  *  *  *
      *  *  *  *  *  *  5  *
      *  *  *  6  *  *  *  *
      *  7  *  *  *  *  *  *
      *  *  *  *  8  *  *  *

    ===============

    ...........

    共有92种方法

4.算法思路:

    这题整体思想是用到递归与回溯,与马踏棋盘非常类似,但是比马踏棋盘问题要难,因为得判断对角线是否冲突,我这里判断是用一个vis[3][20]数组,为什么开始是3呢,因为本身是要判断4个方向不能有皇后的,但是递归是每一列,每一列的递归x,x+1.....这样必然不会在同一列上造成有皇后,则只需要另外3个方向,0表示同一行有皇后,1表示主对角线有皇后,2表示副对角线上有皇后。另外呢,怎么判断这些对角线上是否有皇后 呢?  如果我在第x列,第i行放了元素,那么vis[0][i] = 1表示我在第i行放了元素了。vis[1][x+i] = 1,表示如果我在第x列,第i行放了皇后,那么副对角线上,第x+1列,i-1行数就不能放皇后,第x-1列,第i+1行就不能放皇后,正好都是在副对角线上。vis[2][x-i+8] = 1,表示如果x==i了,那么恒等于vis[2][8] = 1就不能放了,即是主对角线。有了这三个条件既可以了。

5.代码如下:
import java.util.Scanner;

public class EightQueen {
    static int qipan[][] = new int[8][8];
    static int count = 0;
    static int step = 1;
    static int vis[][] = new int[3][20]; //三种情况主对角线,副对角线,行有没有被占用。
    public static void main(String[] args) {
        //初始化棋盘
        for(int i=0;i<8;i++){
            for(int j=0;j<8;j++){
                qipan[i][j] = 0;
            }
        }
        for(int i=0;i<vis.length;i++){
            for(int j=0;j<vis[i].length;j++){
                vis[i][j] = 0;
            }
        }
        
        move(0);
        //从第0个位置开始放第一个皇后,没得说,只要求出皇后的位置,和摆放的数量即可。
        System.out.println("count = " + count);
    }
    public static void move(int x) {
        int next_x = x+1;
        if(step>8){
            for(int i=0;i<8;i++){
                for(int j=0;j<8;j++){
                    if(qipan[i][j] == 0){
                        System.out.printf("%3c",'*'); //把没有皇后,棋盘是0的位置用*输出,显得好看一点
                    }else{
                        System.out.printf("%3d",qipan[i][j]);
                    }
                    
                }
                System.out.println();
            }
            System.out.println("========================");
            count++;
        }else{
            for(int i=0;i<8;i++){
                if(vis[0][i]==0 && vis[1][x+i]==0 && vis[2][x-i+8]==0){//满足摆放条件
                    qipan[x][i] = step;
                    step++;
                    vis[0][i]=1; vis[1][x+i]=1; vis[2][x-i+8]=1;
                    move(next_x);
                    qipan[x][i] = 0;
                    vis[0][i]=0; vis[1][x+i]=0; vis[2][x-i+8]=0;
                    step--;
                    
                }
            }
        }
    }
}