八皇后问题--递归
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;
}
在一个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;
}