您的位置:首页 > 其它

八皇后问题(递归解法)

2017-06-06 10:57 483 查看


八皇后问题,即在一个8*8的棋盘上放8个皇后,使得这8个皇后无法互相攻击( 任意2个皇后不能处于同一行,同一列或是对角线上),输出所有可能的摆放情况。

Write an algorithm to print all ways of arranging eight queens on a chess board so that none of them share the same row, column or diagonal.

八皇后是个经典的问题,如果每个格子都去考虑放皇后与否,一共有2的64次方 种可能,所以不是好方法。

因为每行只能有一个皇后, 所以可以不考虑行,只是用一个一维数组来表示皇后在行上的位置就可以了。

即第1次考虑把皇后放在第1行的某个位置, 第2次放的时候就不用去放在第一行了,因为这样放皇后间是可以互相攻击的。

第2次就考虑把皇后放在第2行的某个位置,第3次考虑把皇后放在第3行的某个位置, 这样依次去递归。

每计算1行,递归一次,每次递归里面考虑8列, 即对每一行皇后有8个可能的位置可以放。

找到一个与前面行的皇后都不会互相攻击的位置, 然后再递归进入下一行。找到一组可行解即可输出,然后程序回溯去找下一组可靠解。

用一个一维数组来表示皇后在行上的位置(也就是列),比如queens[r]=c表示, 第r行的皇后放在第c列。如果当前行是x,皇后放在queens[x]列。

一共有8列,所以我们要让queens[r]依次取第0列,第1列,第2列……一直到第7列, 每取一次考虑皇后放的位置会不会和前面已经放了的皇后有冲突。

也就是说避免同行,同列,对角线。

由于已经不会同行了,所以不用考虑这一点。

同列:queens[r]==queens[r1];

同对角线有两种可能,即主对角线方向和副对角线方向。主对角线方向满足,行之差等于列之差:r-r1==queens[r]-queens[r1]; 副对角线方向满足,行之差等于列之差的相反数:r-r1==queens[r1]-queens[r]。

只有满足了当前皇后和前面所有的皇后都不会互相攻击的时候,才能进入下一级递归.

Java代码:

public class EightQueens{
//棋盘容量
public static final int SIZE=8;
//表示皇后在行上位置的一维数组
private int[] queens=new int[SIZE];
//方案数目
private int answers=0;

public EightQueens(){
search(0);
System.out.println("There are "+answers+" methods");
}
//打印解法,#代表放置皇后,o代表空
public void print(){
System.out.println("method"+(answers+1));
for(int r=0;r<SIZE;r++){
for(int column=0;column<SIZE;column++){
if(column==queens[r])
System.out.print("#");
else
System.out.print("o");
}
System.out.println();
}
System.out.println();
}
//为指定一行寻找解法
public void search(int row){
if(row==SIZE){
print();
++answers;
return;
}

for(int r=0;r<SIZE;r++){
queens[row]=r;
boolean ok=true;
//确保没有同一列,主对角线,副对角线
for(int r1=0;r1<row;r1++)
if(queens[row]==queens[r1]
||row-r1==queens[row]-queens[r1]
||row-r1==queens[r1]-queens[row]){
ok=false;
break;
}
//递归查找
if(ok) search(row+1);
}
}

public static void main(String[] args){
EightQueens eq=new EightQueens();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  八皇后 递归 算法