您的位置:首页 > 其它

八皇后问题--递归

2008-09-19 10:52 190 查看
问题描述:

在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。问共有多少种不同的方法。

程序:

public void testEightPrince() {

// grids代表8*8的棋盘,如果值为TRUE,表示可以此位置为空,还可以放置一个皇后

boolean[][] grids = new boolean[8][];

for (int index = 0; index < grids.length; index++) {

grids[index] = new boolean[8];

}

// 初始化,所有的位置都可以放置一个皇后

for (int x = 0; x < grids.length; x++) {

for (int y = 0; y < grids[x].length; y++) {

grids[x][y] = true;

}

}

int x = 0, y = 0;

for (x = 0; x < 8; x++) {

enableAllPos(grids);

// 把皇后放在x,y处。要做的是把其同一行,同一列或者同一对角线统统置成不能放皇后的棋盘

disablePos(grids, x, y);

// 递归判断此种情况下可以放置的所有可能

canLay(grids, x, y, 1, "");

}

}

// 使棋盘所有的位置都可以放置一个皇后,回到最初始的状态

public void enableAllPos(boolean[][] grids) {

for (int x = 0; x < grids.length; x++) {

for (int y = 0; y < grids[x].length; y++) {

grids[x][y] = true;

}

}

}

/**

* 把棋盘的x,y点所对应的行,列,对角线上的值置成不能放皇后

*

* @param grids

* @param x

* @param y

*/

public void disablePos(boolean[][] grids, int x, int y) {

// 同一行或者同一列

for (int j = 0; j < 8; j++) {

grids[x][j] = false;

grids[j][y] = false;

}

// 右对角线

int count = 1;

while (x + count <= 7 && y + count <= 7) {

grids[x + count][y + count] = false;

count++;

}

count = 1;

while (x - count >= 0 && y - count >= 0) {

grids[x - count][y - count] = false;

count++;

}

// 左对角线

count = 1;

while (x - count >= 0 && y + count <= 7) {

grids[x - count][y + count] = false;

count++;

}

count = 1;

while (x + count <= 7 && y - count >= 0) {

grids[x + count][y - count] = false;

count++;

}

}

public boolean canLay(final boolean[][] grids, int xPos, int yPos,

int level, String temp) {

if (level == 8) {

boolean result = hasEmptyPos(grids);

if (result) {

System.out.println(" 节点序列:" + temp + ",(" + xPos + "," + yPos

+ ")");

}

// System.out.println(" level 到达最大:" + hasEmptyPos(grids));

return result;

}

/**

* 保持当前棋盘现场,复制一个棋盘供下一步调用

*/

boolean[][] newGrids = new boolean[8][8];

for (int x = 0; x < 8; x++) {

for (int y = 0; y < 8; y++) {

newGrids[x][y] = grids[x][y];

}

}

disablePos(newGrids, xPos, yPos);

Position[] poses = getEmptyPos(newGrids, xPos);

if (poses == null || poses[0] == null) {

return false;

}

for (int posIndex = 0; posIndex < poses.length; posIndex++) {

if (canLay(newGrids, poses[posIndex].xPos, poses[posIndex].yPos,

level + 1, temp + "(" + xPos + "," + yPos + "),")) {

// return true;//当只需找出一种可行解,而不是所有的放置情况,可以把去掉此句的注释,注释掉表示得到所有的解

}

}

return false;

}

private class Position {

int xPos = 0;

int yPos = 0;

}

/**

* 取得当前棋盘的下一个可放皇后位置的点的集合,这个决定了搜索空间的大小, 下面采用了最大减少搜索空间的方法,即下一个可放位置点的结合从上一个可放

* 位置的下一个x方向的位移上取得。保证了算法的效率,如果整个棋盘扫描, 效率很低,而且会出现重复的情况。

*

* @param grids

* 当前棋盘

* @param prevXpos

* 上一个可放位置的x的坐标

* @return

*/

public Position[] getEmptyPos(boolean[][] grids, int prevXpos) {

ArrayList<Position> list = new ArrayList<Position>();

// 下一个x方向的位置

int x = (prevXpos + 1) % 8;

for (int y = 0; y < 8; y++) {

if (grids[x][y]) {

Position pos = new Position();

pos.xPos = x;

pos.yPos = y;

list.add(pos);

}

}

/*

* for(int x = 0; x < 8; x++){ for(int y = 0; y < 8; y++){

* if(grids[x][y]){ Position pos = new Position(); pos.xPos = x;

* pos.yPos = y; list.add(pos); } } }

*/

return list.toArray(new Position[1]);

}

public boolean hasEmptyPos(boolean[][] grids) {

for (int x = 0; x < grids.length; x++) {

for (int y = 0; y < grids[x].length; y++) {

if (grids[x][y] == true) {

return true;

}

}

}

return false;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: