使用回溯法和子集树(降维法)解决N皇后问题

之前写过一篇也是关于N皇后的博客使用回溯法解决八皇后问题,不过当初使用的是二维数组存储。不仅是空间开销还是子集规模都非常大。
这里大致说下二维数组的子集规模计算方法
例如是4x4。如果按照二维数组存放,设二维数组为x[4][4]
x[0][0]有1(摆放)和0(不摆放)两种可能,对应的x[0][1]也有0和1的可能。所以可以用下面的树(排列树)来表示计算开销的规模,一共会有16层。所以解空间树规模(最底层)为2(n^2) = 216 = 65536
在这里插入图片描述

下面介绍仅使用一维数组就能解决此问题的方式。
设数组为x[4]。这代表什么意思呢?例如x[0] = 1,x[1] = 3,x[2] = 0,x[3] = 2
x[0] = 1就代表皇后摆放在第一行的第2个位置。
x[1] = 3就代表皇后摆放在第二行的第4个位置。
如下:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
子集规模树(子集树),一共有4层,解空间树规模(最底层)为nn = 44 = 256,相比较于前面的65536已经是非常小了,如果n在大些,后者基本都可以忽略不计。
在这里插入图片描述

代码实现

public class NQueens {

    /**
     * 皇后个数
     */
    private int n;

    /**
     * 当前解
     */
    private int[] currentSolution;

    /**
     * 当前已经找到可行的方案个数
     */
    private long sum;

    public NQueens(int n) {
        this.n = n;
        this.sum = 0;
        this.currentSolution = new int[n];
        backtrack(0);
    }

    public boolean isSuitablePlacement(int t) {
        // 因为是对称的,所以第一行只需要计算一半即可
	if(t == 0) {
	    if((n + 1) / 2 <= currentSolution[t]) {
	        return false;
	    }
	}
	for(int i = 0; i < t; i++) {
            // 判断列
            if(currentSolution[i] == currentSolution[t]) {
                return false;
            }
            // 判断斜向,这里通过斜率判断
            if(Math.abs(currentSolution[i] - currentSolution[t]) == t - i) {
                return false;
            }
        }
        return true;
    }

    public void saveResult() {
        // 这里可以打印放置情况
    }

    public void backtrack(int t) {
        if(t >= n) {
            sum++;
            saveResult();
            return;
        }
        for(int i = 0; i < n; i++) {
            currentSolution[t] = i;
            // 判断摆放是否合适,不合适就回溯
            if(isSuitablePlacement(t)) {
               backtrack(t + 1);
            }
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        NQueens nQueens = new NQueens(12);
        System.out.println(nQueens.sum);
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

最后对比下一维和二维时间上的差距

12皇后
二维所需时间(单位毫秒): 1080
一维所需时间(单位毫秒): 207
13皇后
二维所需时间(单位毫秒): 4252
一维所需时间(单位毫秒): 1108
14皇后
二维所需时间(单位毫秒): 21358
一维所需时间(单位毫秒): 6331

当然了,还能运用减枝的方法进一步优化
使用回溯法和排列树(降维和减枝)解决N皇后问题

发布了54 篇原创文章 · 获赞 36 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/XlxfyzsFdblj/article/details/84573883
今日推荐