八皇后算法描述如下:
在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法!
image.png

下面来分析一波,假设此时我们想要在黑色方块位置放置一个皇后:
image.png

如果一列一列的放置皇后的话,图中黑色位置能放置一个皇后的合法性条件为:
1、绿色线条经过的方格没有皇后 (不处于同一斜线)
2、红色线条经过的方格没有皇后 (不处于同一行)
3、紫色线条经过的方格没有皇后 (不处于同一斜线)

也就是说如果以黑色方块位置为参照原点:(0,0)坐标点,紫色和绿色两个线条分别是斜率为1和-1的两个函数,如下图:
紫色线所代表的函数是:y = -x;
绿色先所代表的函数是:y=x;
(横坐标是列,纵坐标为行,注意行从上到下递增)
image.png

凡是位于这两条函数线上的位置(点)以及横坐标(说明位于同一行)都不能有皇后。也即行和列的差值要相等,如图所示
image.png
Java代码实现:

public class EightQueenMain {

  private static int[] queen = new int[]{-1, -1, -1, -1, -1, -1, -1, -1};
  private static int count = 0;

  public static void main(String[] args) {
    eightQueue(0);
    System.out.println(count);
  }

  private static boolean isLegal(int currentRow, int currentCol) {
    for (int col = 0; col < currentCol; col++) {
      if (currentRow == queen[col]) { // 只判断行相等,因为是按列放皇后的
        return false;
      }
      if (Math.abs(queen[col] - currentRow) == Math.abs(col - currentCol)) { // 在斜线上(行列差值相等)
        return false;
      }
    }
    return true;
  }

  private static void eightQueue(int currentCol) {
    for (int row = 0; row < 8; row++) {
      if (isLegal(row, currentCol)) {
        queen[currentCol] = row;
        if (currentCol == 7) { // 到达最后一列获得正确结果
          count++;
        }
        eightQueue(currentCol + 1);
      }
    }

  }
}
输出92

参考链接:八皇后回溯算法原理剖析及其JS实现


花溪的小石头
180 声望8 粉丝

境由心造,一切只在当下的转念之间。