N-Queens

N-Queens (leetcodelintcode)

Description
The n-queens puzzle is the problem of placing n queens on an n×n chessboard 
such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, 
where 'Q' and '.' both indicate a queen and an empty space respectively.

Example
There exist two distinct solutions to the 4-queens puzzle:
[
  // Solution 1
  [".Q..",
   "...Q",
   "Q...",
   "..Q."
  ],
  // Solution 2
  ["..Q.",
   "Q...",
   "...Q",
   ".Q.."
  ]
]

Challenge 
Can you do it without recursion?

解题思路

在国际象棋中,皇后是战斗力最强的一个棋子,可以横、竖、斜走,吃子和走法相同。

本题目的问题是如何在一个n * n的棋盘上面摆放n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?根据国际象棋的规则,要达到要求,任意两个皇后都不能处在同一行、同一列、同一斜线上面。

4 * 4棋盘为例,将解决方案中每一行皇后所在列放入一维数组中,两个解决方案分别为[2, 4, 1, 3][3, 1, 4, 2]数组索引表示皇后所在行,数组元素表示皇后所在列,不难发现,这其实是[1, 2, 3, 4]全排列的一部分。所以问题可以转化为①求解所有全排列;②判断全排列是否满足规则要求。

全排列问题使用DFS搜索即可,我们来看一下如何判断摆放位置是否符合要求。

  • 一、不能在同一行,考虑到一维数组索引表示行,所以这个条件是必然满足的;
  • 二、不能在同一列,需要将已存入数组的每一个元素值与即将存入的元素比较,两者不同时才可以存入;
  • 三、不能在同一斜线,分为两种,左上到右下,右上到左下,如下图所示,两种情况下“斜率”的绝对值都是 1 ,以此作为判断依据。(注:这里的斜率并不是在常规的笛卡尔坐标系)
1, 1 1, 2 1, 3 1, 4
2, 1 2, 2 2, 3 2, 4
3, 1 3, 2 3, 3 3, 4
4, 1 4, 2 4, 3 4, 4

Java 实现

class
Solution
{

/**
     * Get all distinct N-Queen solutions
     * 
@param
 n: The number of queens
     * 
@return
: All distinct solutions
     * For example, A string '...Q' shows a queen on forth position
     */

    ArrayList
<
ArrayList
<
String
>
>
 solveNQueens(
int
 n) {
        ArrayList
<
ArrayList
<
String
>
>
 result = 
new
 ArrayList
<
>
();

if
 (n 
<
= 
0
) {

return
 result;
        }

        search(n, 
new
 ArrayList
<
Integer
>
(), result);

return
 result;
    }


private
void
search
(
int
 n,
                        ArrayList
<
Integer
>
 cols,
                        ArrayList
<
ArrayList
<
String
>
>
 result)
{

if
 (cols.size() == n) {
            result.add(drawChessboard(cols));

return
;
        }          

// cols: index i is row-coordinate 
&
&
 cols.get(i) is column-coordinate
// for col : the coordinate is (cols.size(), col)
// col: [0...n-1] form a permutation of column
for
 (
int
 col = 
0
; col 
<
 n; col++) {

if
 (!isValid(cols, col)) {

continue
;
            }
            cols.add(col);
            search(n, cols, result);
            cols.remove(cols.size() - 
1
);
        }
    }


private
 ArrayList
<
String
>
drawChessboard
(ArrayList
<
Integer
>
 cols)
{
        ArrayList
<
String
>
 chessboard = 
new
 ArrayList
<
>
();

for
 (
int
 i = 
0
; i 
<
 cols.size(); i++) {
            StringBuilder cb = 
new
 StringBuilder();

for
 (
int
 j = 
0
; j 
<
 cols.size(); j++) {

if
 (j == cols.get(i)) {
                    cb.append(
'Q'
);
                } 
else
 {
                    cb.append(
'.'
);
                }
            }
            chessboard.add(cb.toString());
        }

return
 chessboard;
    }


private
boolean
isValid
(ArrayList
<
Integer
>
 cols, 
int
 col)
{

int
 row = cols.size();

// queen‘s coodinate in cols [i, cols.get(i)] vs queen to be added [row, col]
for
 (
int
 i = 
0
; i 
<
 row; i++) {

// same column
if
 (cols.get(i) == col) {

return
false
;
            }

// left-top to right-bottom 
&
&
 right-top to left-bottom
if
 (Math.abs(i - row) == Math.abs(cols.get(i) - col)) {

return
false
;
            }
        }

return
true
;
    }

}

参考

  1. N-Queens | 九章算法
  2. N-Queens leetcode java | 爱做饭的小莹子

results matching ""

    No results matching ""