八皇后问题

八皇后问题

八皇后问题:
八皇后问题(英文:Eight queens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

7皇后
6皇后
5皇后
4皇后
3皇后
2皇后
1皇后
0皇后
y /x01234567

下面我们来写代码

首先我们先创建一个成员变量用来记下成功的次数

创建一个长度为8的数组,其索引值为y,数组里存的值为x,用于记录皇后放的位置

public class EightQueen {
	int count = 0;
	int[] queen = new int[8];
}

皇后有点位置可以放。而有的位置不能放,所以我们就需要定义一个方法来判断皇后是否可以放置。

由于第一个皇后可以随意放,所以我们可以直接返回true

public boolean isPut(int x, int y) {
	if(y == 0){
		return true;
	}
}

然后判断后续皇后所放置的位置,由于任意两个皇后都不能处于同一行、同一列或同一斜线上,所以

  1. 同一行:由于用数组索引记录的y值,所以不会出现在同一行的情况。
  2. 同一列: 就是所判断位置的x值与之前放置的皇后的x值是否相等。
  3. 同一斜线:可以使用斜率来进行判断,同一斜线上上的斜率为正负1,也就是(y1-y2)/ (x1-x2)=正负1;也就可以理解成(y1-y2)的绝对值与(x1-x2)的绝对值相等。

实例如下:

public boolean isPut(int x, int y) {
    if(y == 0){
        return true;
    }
    for (int i = 0; i < y; i++) {
        if (Math.abs(y - i) == Math.abs(x - queen[i]) || x == queen[i]){
            return false;
        }
    }
    return true;
}

接着就到了我们的主体部分(这里我们使用递归来解决)

首先我们要先写好递归的出口,由于我们只需要放置8位皇后,所以我们可以使用数组queen的索引来进行计数,当其超过7时,则结束。此时我们的成功次数的计数器(count)加一,并通过Arrays.toString(queen)方法将8为皇后的位置打印出来。

public void eightQueen(int y) {
    if (y > 7) {
        count++;
        System.out.println(Arrays.toString(queen));
        return;
    }
}

然后通过一个for循环,对同一行的每个位置都进行判断,如果可以放置,则将其x值赋给queen[y],并继续放置下一位皇后。

public void eightQueen(int y) {
    if (y > 7) {
        count++;
        System.out.println(Arrays.toString(queen));
        return;
    }
    for (int i = 0; i < 8; i++) {
        if (isPut(i, y)) {
            queen[y] = i;
            eightQueen(y + 1);
        }
    }
}

程序写到这里基本上已经结束了,我们只需要在main方法中写上测试就可以运行了

下面是我整个程序的代码

import java.util.Arrays;

public class EightQueen {
	//记录成功的次数
	int count = 0;
	//记录皇后放的位置,其索引值为y,数组里存的值为x
	int[] queen = new int[8];

	//判断皇后在(x,y)位置处是否可以放置
	public boolean isPut(int x, int y) {
		if (y == 0) {
			return true;
		}
		for (int i = 0; i < y; i++) {
			if (Math.abs(y - i) == Math.abs(x - queen[i]) || x == queen[i]) {
				return false;
			}
		}
		return true;
	}

	//通过递归判断皇后放置的位置
	public void eightQueen(int y) {
		if (y > 7) {
			count++;
			System.out.println(Arrays.toString(queen));
			return;
		}
		for (int i = 0; i < 8; i++) {
			if (isPut(i, y)) {
				queen[y] = i;
				eightQueen(y + 1);
			}
		}
	}

	public static void main(String[] args) {
		EightQueen e = new EightQueen();
		e.eightQueen(0);
		System.out.println(e.count);
	}
}

一共 92 种排法。代码还是很容易能够看的懂的。只要思路清晰,大家就可以一步步的实现代码。文中若有不对的地方,还请大神指点指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值