Java数据结构算法之八皇后问题

八皇后问题是由国际象棋手马克斯-贝瑟于1848年提出的问题,是回溯算法的经典案例。

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

答案是92种,一维数组和二维数组都可以用来解决该问题,在这里使用一维数组模拟解决该问题,其中一维数组有八个元素,每个元素的位置标号代表第几行,而每个元素的值代表是在该行的第几列。

例如:0 6 4 7 1 3 5 2 就代表八个皇后被摆放在(0,0),(1,6),(2,4),(3,7),(4,1),(5,3),(6,5),(7,2)八个位置

1.基本思路

先在某行的第一列位置放置一个皇后,再和其他所有已经放置的进行比较,当不冲突时就去下一行放置下一个皇后,否则放于这一行的第二列,再判断是否符合条件。

假如某行的八个列都不能放置,那么就回溯至上一层,调整上一层的皇后位置,如此递归调整,直到所有的8个皇后符合条件。

2.代码实现

        2.1 Queue8类

package 八皇后问题;

/**
 * @Classname Queue8
 * @Description 使用一维数组解决8皇后问题
 * @Date 2022/6/16 21:09
 * @Created by jiawen
 */
public class Queue8 {
    private int max = 8;
    private int[] arr = new int[max];
     int count = 0;


    private boolean checkConflict(int n) {//false代表冲突;true代表不冲突
        for (int i = 0; i < n; i++) {
            if (arr[i] == arr[n] || Math.abs(i - n) == Math.abs(arr[i] - arr[n])) {
                //无需考虑是否在同一行,当使用一维数组实现的时候,任何两个皇后都不会在同一行,只需判断是否同一列或者对角
                //Math.abs(i - n) == Math.abs(arr[i] - arr[n]),类似于斜率,左边为行差,右侧为列差,当二者相等时,证明处于斜对角
                return false;
            }
        }

        return true;
    }

    //queueNumber代表放置的第几个queue
     void placeQueue(int queueNumber) {
        if (queueNumber == max) {
            //注意,这里是queueNumber == max(放置数=8)时结束方法,
            //当放置数=8时证明这是在放置第九个皇后,那么这个皇后无需放置,直接return
            listArr();
            return;
        }
        for (int i = 0; i < max; i++) {
            //i代表的是放置的列,由于我们使用一维数组代替,所以arr的某个元素的数值就代表第几列,该数值加1,就代表在这一行移动了一列
            arr[queueNumber] = i;//一开始i为0,证明在第0列
            if (checkConflict(queueNumber)) {//如果不冲突,在这个放置的基础上放置下一个
                placeQueue(queueNumber + 1);
            }

        }


    }

    private void listArr() {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");

        }
        System.out.println();
        count++;

    }
}

2.2 主方法

package 八皇后问题;


/**
 * @Classname DemoTest
 * @Description TODO
 * @Date 2022/6/16 21:50
 * @Created by jiawen
 */
public class DemoTest {
    public static void main(String[] args) {
        Queue8 queue8 = new Queue8();
        System.out.println("===============");
        queue8.placeQueue(0);
        System.out.println("===============");
        System.out.println("一共" + queue8.count + "种解法");
    }
}

3. 运行结果

===============
0 4 7 5 2 6 1 3 
0 5 7 2 6 3 1 4 
0 6 3 5 7 1 4 2 
0 6 4 7 1 3 5 2 
1 3 5 7 2 0 6 4 
1 4 6 0 2 7 5 3 
1 4 6 3 0 7 5 2 
1 5 0 6 3 7 2 4 
1 5 7 2 0 3 6 4 
1 6 2 5 7 4 0 3 
1 6 4 7 0 3 5 2 
1 7 5 0 2 4 6 3 
2 0 6 4 7 1 3 5 
2 4 1 7 0 6 3 5 
2 4 1 7 5 3 6 0 
2 4 6 0 3 1 7 5 
2 4 7 3 0 6 1 5 
2 5 1 4 7 0 6 3 
2 5 1 6 0 3 7 4 
2 5 1 6 4 0 7 3 
2 5 3 0 7 4 6 1 
2 5 3 1 7 4 6 0 
2 5 7 0 3 6 4 1 
2 5 7 0 4 6 1 3 
2 5 7 1 3 0 6 4 
2 6 1 7 4 0 3 5 
2 6 1 7 5 3 0 4 
2 7 3 6 0 5 1 4 
3 0 4 7 1 6 2 5 
3 0 4 7 5 2 6 1 
3 1 4 7 5 0 2 6 
3 1 6 2 5 7 0 4 
3 1 6 2 5 7 4 0 
3 1 6 4 0 7 5 2 
3 1 7 4 6 0 2 5 
3 1 7 5 0 2 4 6 
3 5 0 4 1 7 2 6 
3 5 7 1 6 0 2 4 
3 5 7 2 0 6 4 1 
3 6 0 7 4 1 5 2 
3 6 2 7 1 4 0 5 
3 6 4 1 5 0 2 7 
3 6 4 2 0 5 7 1 
3 7 0 2 5 1 6 4 
3 7 0 4 6 1 5 2 
3 7 4 2 0 6 1 5 
4 0 3 5 7 1 6 2 
4 0 7 3 1 6 2 5 
4 0 7 5 2 6 1 3 
4 1 3 5 7 2 0 6 
4 1 3 6 2 7 5 0 
4 1 5 0 6 3 7 2 
4 1 7 0 3 6 2 5 
4 2 0 5 7 1 3 6 
4 2 0 6 1 7 5 3 
4 2 7 3 6 0 5 1 
4 6 0 2 7 5 3 1 
4 6 0 3 1 7 5 2 
4 6 1 3 7 0 2 5 
4 6 1 5 2 0 3 7 
4 6 1 5 2 0 7 3 
4 6 3 0 2 7 5 1 
4 7 3 0 2 5 1 6 
4 7 3 0 6 1 5 2 
5 0 4 1 7 2 6 3 
5 1 6 0 2 4 7 3 
5 1 6 0 3 7 4 2 
5 2 0 6 4 7 1 3 
5 2 0 7 3 1 6 4 
5 2 0 7 4 1 3 6 
5 2 4 6 0 3 1 7 
5 2 4 7 0 3 1 6 
5 2 6 1 3 7 0 4 
5 2 6 1 7 4 0 3 
5 2 6 3 0 7 1 4 
5 3 0 4 7 1 6 2 
5 3 1 7 4 6 0 2 
5 3 6 0 2 4 1 7 
5 3 6 0 7 1 4 2 
5 7 1 3 0 6 4 2 
6 0 2 7 5 3 1 4 
6 1 3 0 7 4 2 5 
6 1 5 2 0 3 7 4 
6 2 0 5 7 4 1 3 
6 2 7 1 4 0 5 3 
6 3 1 4 7 0 2 5 
6 3 1 7 5 0 2 4 
6 4 2 0 5 7 1 3 
7 1 3 0 6 4 2 5 
7 1 4 2 0 6 3 5 
7 2 0 5 1 4 6 3 
7 3 0 2 5 1 6 4 
===============
一共92种解法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值