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:
Input: 4 Output: [ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ] Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
题目意思比较简单,就是给定一个数字N,将N个皇后放在N*N的棋盘上,这N个皇后间相互不能攻击,国际象棋中皇是可以横竖斜着走,这里其实可以用简单的回溯法,由于已经有了一些限制条件,可知所有N个皇后不能在同一行上面,因为可简单按照一行一行来放置皇后。过程如下:
1. 将当前行号设置为0,选择第0行皇后的下一个可选位置,如果无可选位置程序结束,否则进入2
2. 判断当前行放的皇后位置是否合法,如果合法进入3,如果不合法进入4
3. 判断当前行号是否已达到最大,如果最大输出最前解,并到1;否则到下一行,并放置下一行的皇后可选位置
4. 判断当前行是否有下一个可选位置,如果有就放置,并到2;否则回到上一行,并放置上一行的皇后可选位置,并进入2
当回到上一行时,需要记得将本行置为不放置皇后状态,GO实现代码如下:
const (
QUEEN byte = 'Q'
EMPTY byte = '.'
)
// 行号,将当前行号的下一个可选位置
type PosNumber struct {
index int
numbers []int
}
// 判断当前在i, j位置是否可放置皇后
func isValidPos(nQueenSolver [][]byte, n int, i int, j int) bool {
for xIndx := 0; xIndx < i; xIndx++ {
if nQueenSolver[xIndx][j] == QUEEN {
return false
}
}
xIndx := i - 1
yIndx := j - 1
for {
if xIndx < 0 || yIndx < 0 {
break
}
if nQueenSolver[xIndx][yIndx] == QUEEN {
return false
}
xIndx--
yIndx--
}
xIndx = i - 1
yIndx = j + 1
for {
if xIndx < 0 || yIndx >= n {
break
}
if nQueenSolver[xIndx][yIndx] == QUEEN {
return false
}
xIndx--
yIndx++
}
return true
}
func solveNQueens(n int) [][]string {
nQueenSolvers := [][]string{}
nQueenSolver := make([][]byte, n)
for i := 0; i < n; i++ {
nQueenSolver[i] = make([]byte, n)
}
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
for k := 0; k < n; k++ {
nQueenSolver[j][k] = EMPTY
}
}
nQueenSolver[0][i] = QUEEN
// 存储每一行皇后的可选位置
posStack := []PosNumber{}
posStack = append(posStack, PosNumber{0, []int{}})
curXPos := 0
curYpos := i
stepBack := false
for {
if len(posStack) == 0 {
break
}
// 回溯
if stepBack {
if len(posStack[len(posStack)-1].numbers) != 0 {
curXPos = posStack[len(posStack)-1].index
curYpos = posStack[len(posStack)-1].numbers[0]
posStack[len(posStack)-1].numbers = posStack[len(posStack)-1].numbers[1:]
} else {
for len(posStack) > 0 && len(posStack[len(posStack)-1].numbers) == 0 {
for j := 0; j < n; j++ {
nQueenSolver[posStack[len(posStack)-1].index][j] = EMPTY
}
posStack = posStack[0 : len(posStack)-1]
}
if len(posStack) == 0 {
break
}
curXPos = posStack[len(posStack)-1].index
for j := 0; j < n; j++ {
nQueenSolver[curXPos][j] = EMPTY
}
curYpos = posStack[len(posStack)-1].numbers[0]
posStack[len(posStack)-1].numbers = posStack[len(posStack)-1].numbers[1:]
}
stepBack = false
}
if isValidPos(nQueenSolver, n, curXPos, curYpos) {
nQueenSolver[curXPos][curYpos] = QUEEN
if curXPos == n-1 {
nStr := make([]string, n)
for j := 0; j < n; j++ {
nStr[j] = string(nQueenSolver[j])
}
nQueenSolvers = append(nQueenSolvers, nStr)
nQueenSolver[curXPos][curYpos] = EMPTY
stepBack = true
continue
}
curXPos++
curYpos = 0
numbers := []int{}
for j := 1; j < n; j++ {
numbers = append(numbers, j)
}
posStack = append(posStack, PosNumber{curXPos, numbers})
} else {
stepBack = true
}
}
}
return nQueenSolvers
}