五大算法之回溯法

问题:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

抽象:n后问题等价于在n×n的棋盘上放置n个棋子,任何2个棋子不在同一行或同一列或同一斜线上。

思路:要解决N皇后问题,其实就是要解决好怎么放置这n个皇后,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线,在这里我们可以以行优先,就是说皇后的行号按顺序递增,只考虑第i个皇后放置在第i行的哪一列,所以在放置第i个皇后的时候,可以从第1列判断起,如果可以放置在第1个位置,则跳到下一行放置下一个皇后。如果不能,则跳到下一列...直到最后一列,如果最后一列也不能放置,则说明此时放置方法出错,则回到上一个皇后向之前放置的下一列重新放置。此即是回溯法的精髓所在。当第n个皇后放置成功后,即得到一个可行解,此时再回到上一个皇后重新放置寻找下一个可行解...如此后,即可找出一个n皇后问题的所有可行解。

代码如下:

package test;
 
/**
 * 回溯法求N皇后问题
 * 
 * @author yanghang
 *
 */
public class Huisu {
    static int n = 14; // 皇后个数,n必须大于0
    static int sum = 0; // 可行解个数
    static int[] x = new int[n + 1]; // 皇后放置的列数,从1开始
 
    /**
     * 计算当前摆放位置是否可行
     * 
     * @param k
     * @return
     */
    public static boolean place(int k) {
        int i;
        for (i = 1; i < k; i++)
            if (Math.abs(k - i) == Math.abs(x[k] - x[i]) || x[k] == x[i])
                return false;
        return true;
    }
 
    /**
     * 递归求解,时间复杂度为为n!
     * 
     * @param t
     * @return
     */
    public static int backtrace(int t) {
        // 当放置的皇后超过n时,可行解个数加1
        if (t > n)
            sum++;
        else
            for (int i = 1; i <= n; i++) {
                // 标明第t个皇后放在第i列
                x[t] = i;
                // 如果可以放在某一位置,则继续放下一皇后
                if (place(t))
                    backtrace(t + 1);
            }
        return sum;
    }
 
    /**
     * 递推求解,时间复杂度为为n!
     * @return
     */
    public static int backtrace() {
        //将当前列初始化为0
        x[1] = 0;
        //从第一行开始试探
        int t = 1;
        while (t > 0) {
            //往前挪一列
            x[t] += 1;
            //列没出界并且当前摆放位置不可行,继续向前挪一列
            while (x[t] <= n && !place(t))
                x[t]++;
            //当前列还未出界,可行位置
            if (x[t] <= n)
                //已经是最后一行
                if (t == n)
                    sum++;
                //不是最后一行,行数加一,继续试探
                else
                    x[++t] = 0;
            //当前列已出界,则返回上一行继续试探
            else
                t--;
        }
        return sum;
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(backtrace(1));
    }
 
}

猜你喜欢

转载自blog.csdn.net/u010227646/article/details/80015220