八皇后问题--递归

问题描述:

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

 

程序:

  1.     public void testEightPrince() {
  2.         // grids代表8*8的棋盘,如果值为TRUE,表示可以此位置为空,还可以放置一个皇后
  3.         boolean[][] grids = new boolean[8][];
  4.         for (int index = 0; index < grids.length; index++) {
  5.             grids[index] = new boolean[8];
  6.         }
  7.         // 初始化,所有的位置都可以放置一个皇后
  8.         for (int x = 0; x < grids.length; x++) {
  9.             for (int y = 0; y < grids[x].length; y++) {
  10.                 grids[x][y] = true;
  11.             }
  12.         }
  13.         int x = 0, y = 0;
  14.         for (x = 0; x < 8; x++) {
  15.             enableAllPos(grids);
  16.             // 把皇后放在x,y处。要做的是把其同一行,同一列或者同一对角线统统置成不能放皇后的棋盘
  17.             disablePos(grids, x, y);
  18.             // 递归判断此种情况下可以放置的所有可能
  19.             canLay(grids, x, y, 1"");
  20.         }
  21.     }
  22.     // 使棋盘所有的位置都可以放置一个皇后,回到最初始的状态
  23.     public void enableAllPos(boolean[][] grids) {
  24.         for (int x = 0; x < grids.length; x++) {
  25.             for (int y = 0; y < grids[x].length; y++) {
  26.                 grids[x][y] = true;
  27.             }
  28.         }
  29.     }
  30.     /**
  31.      * 把棋盘的x,y点所对应的行,列,对角线上的值置成不能放皇后
  32.      * 
  33.      * @param grids
  34.      * @param x
  35.      * @param y
  36.      */
  37.     public void disablePos(boolean[][] grids, int x, int y) {
  38.         // 同一行或者同一列
  39.         for (int j = 0; j < 8; j++) {
  40.             grids[x][j] = false;
  41.             grids[j][y] = false;
  42.         }
  43.         // 右对角线
  44.         int count = 1;
  45.         while (x + count <= 7 && y + count <= 7) {
  46.             grids[x + count][y + count] = false;
  47.             count++;
  48.         }
  49.         count = 1;
  50.         while (x - count >= 0 && y - count >= 0) {
  51.             grids[x - count][y - count] = false;
  52.             count++;
  53.         }
  54.         // 左对角线
  55.         count = 1;
  56.         while (x - count >= 0 && y + count <= 7) {
  57.             grids[x - count][y + count] = false;
  58.             count++;
  59.         }
  60.         count = 1;
  61.         while (x + count <= 7 && y - count >= 0) {
  62.             grids[x + count][y - count] = false;
  63.             count++;
  64.         }
  65.     }
  66.     public boolean canLay(final boolean[][] grids, int xPos, int yPos,
  67.             int level, String temp) {
  68.         if (level == 8) {
  69.             boolean result = hasEmptyPos(grids);
  70.             if (result) {
  71.                 System.out.println(" 节点序列:" + temp + ",(" + xPos + "," + yPos
  72.                         + ")");
  73.             }
  74.             // System.out.println(" level 到达最大:" + hasEmptyPos(grids));
  75.             return result;
  76.         }
  77.         /**
  78.          * 保持当前棋盘现场,复制一个棋盘供下一步调用
  79.          */
  80.         boolean[][] newGrids = new boolean[8][8];
  81.         for (int x = 0; x < 8; x++) {
  82.             for (int y = 0; y < 8; y++) {
  83.                 newGrids[x][y] = grids[x][y];
  84.             }
  85.         }
  86.         disablePos(newGrids, xPos, yPos);
  87.         Position[] poses = getEmptyPos(newGrids, xPos);
  88.         if (poses == null || poses[0] == null) {
  89.             return false;
  90.         }
  91.         for (int posIndex = 0; posIndex < poses.length; posIndex++) {
  92.             if (canLay(newGrids, poses[posIndex].xPos, poses[posIndex].yPos,
  93.                     level + 1, temp + "(" + xPos + "," + yPos + "),")) {
  94.                 // return true;//当只需找出一种可行解,而不是所有的放置情况,可以把去掉此句的注释,注释掉表示得到所有的解
  95.             }
  96.         }
  97.         return false;
  98.     }
  99.     private class Position {
  100.         int xPos = 0;
  101.         int yPos = 0;
  102.     }
  103.     /**
  104.      * 取得当前棋盘的下一个可放皇后位置的点的集合,这个决定了搜索空间的大小, 下面采用了最大减少搜索空间的方法,即下一个可放位置点的结合从上一个可放
  105.      * 位置的下一个x方向的位移上取得。保证了算法的效率,如果整个棋盘扫描, 效率很低,而且会出现重复的情况。
  106.      * 
  107.      * @param grids
  108.      *            当前棋盘
  109.      * @param prevXpos
  110.      *            上一个可放位置的x的坐标
  111.      * @return
  112.      */
  113.     public Position[] getEmptyPos(boolean[][] grids, int prevXpos) {
  114.         ArrayList<Position> list = new ArrayList<Position>();
  115.         // 下一个x方向的位置
  116.         int x = (prevXpos + 1) % 8;
  117.         for (int y = 0; y < 8; y++) {
  118.             if (grids[x][y]) {
  119.                 Position pos = new Position();
  120.                 pos.xPos = x;
  121.                 pos.yPos = y;
  122.                 list.add(pos);
  123.             }
  124.         }
  125.         /*
  126.          * for(int x = 0; x < 8; x++){ for(int y = 0; y < 8; y++){
  127.          * if(grids[x][y]){ Position pos = new Position(); pos.xPos = x;
  128.          * pos.yPos = y; list.add(pos); } } }
  129.          */
  130.         return list.toArray(new Position[1]);
  131.     }
  132.     public boolean hasEmptyPos(boolean[][] grids) {
  133.         for (int x = 0; x < grids.length; x++) {
  134.             for (int y = 0; y < grids[x].length; y++) {
  135.                 if (grids[x][y] == true) {
  136.                     return true;
  137.                 }
  138.             }
  139.         }
  140.         return false;
  141.     }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值