问题描述:
在一个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;
- }