回溯法之八皇后问题

82年,有人提出了一个堪称经典的算法问题,八皇后问题,题目如下:有一个8*8的棋盘,问,有多少种摆法,能够让8个皇后分布在棋盘上,从而不会被对方吃掉?

首先,介绍一下规则,皇后在国际象棋中,能够吃掉位于其一条线上或者斜线上的棋子,这比象棋中的车要厉害的多,可以斜着走。那么解决这个问题的思路是什么呢?听我讲完你就明白了!

1:我们在第一行随意摆放一个皇后,那么这个肯定满足了规则,不会被吃掉;

2:在第二行,我们从第一列开始摆放皇后,然后判断是够满足规则,如果不满足,则放入第二列,如果第二行所有列,都不满足,则回到第一步,重新摆放第一个皇后;

3:前两行满足两件后,第三行也是如上的步骤,若不满足条件,则向上改变已摆好的皇后位置,直到满足条件。

这个就是回溯法,也就是暴力拆解,类似于走迷宫,当一条路线不满足条件,返回上一步,重新进行。

用java表示代码如下:

public class Queen{
    static int n = 8; //皇后的个数
    static int total = 0;  //摆放方法数
    static int c[] = new int[8];  //存放皇后位置
    public static void main(String[] args) {
        int total_sum = queue(0);  //从0行开始摆放
        System.out.println(total_sum);
    }

    static boolean is_ok(int row){
        for (int j=0;j!=row;j++){
            if (c[row] == c[j] || row - c[row] == j - c[j] || row + c[row] == j+c[j]){
                return false;
            }
        }
        return true;
    }

    static int queue(int row){
        if (row == n){
            //当 行数=皇后数目,即最后一行也已经摆放好了,所以解法加1
            return ++total;  
        }else{
            for (int j=0;j < n;j++){
                //这里很关键  我们让数组记录下 皇后所在的列数
                c[row] = j;
                if (is_ok(row)){
                    //满足规则 递归调用
                    queue(row+1);
                }
            }
        }
        return total;
    }
}

这里我来解释一下is_ok()这个函数的原理,你可以将8*8的期盼想想成一个想x,y坐标轴,x为数组的下标,y为数组的下标对应的值,这样,我们判断皇后摆放是否正确的问题就转化成,判断两两(x,y)坐标组成的直线的斜率了,当斜率为1,-1的时候,就不满足条件了,这样is_ok函数就很好理解了。

猜你喜欢

转载自blog.csdn.net/fly_rice/article/details/82555907