我正在尝试解决N皇后问题。 您可以在https://leetcode.com/problems/n-queens/中找到问题。
对于回溯,我了解到我们可以通过三个键来解决问题:
做出选择
约束
目标
所以我想出了这个解决方案:
func solveNQueens(_ n: Int) -> [[String]] {
typealias ChessBoard = [[Int]]
var result = Set<ChessBoard>()
func getIndexsOfDiagonal(row:Int,column:Int) -> [(row:Int,col:Int)] {
var indexs = [(Int,Int)]()
var rowIndex = row
var colIndex = column
while rowIndex < n && colIndex < n {
indexs.append((rowIndex,colIndex))
rowIndex += 1
colIndex += 1
}
rowIndex = row
colIndex = column
while rowIndex >= 0 && colIndex >= 0 {
indexs.append((rowIndex,colIndex))
rowIndex -= 1
colIndex -= 1
}
rowIndex = row
colIndex = column
while rowIndex >= 0 && colIndex < n {
indexs.append((rowIndex,colIndex))
rowIndex -= 1
colIndex += 1
}
rowIndex = row
colIndex = column
while rowIndex < n && colIndex >= 0 {
indexs.append((rowIndex,colIndex))
rowIndex += 1
colIndex -= 1
}
return indexs
}
func placeQuees(chessboard:ChessBoard,row:Int,column:Int) ->ChessBoard {
var newChessBorad = chessboard
//set row
for index in 0..<n {
newChessBorad[row][index] = -1
}
//set column
for index in 0..<n {
newChessBorad[index][column] = -1
}
//set diagonal
for index in getIndexsOfDiagonal(row:row,column:column) {
newChessBorad[index.row][index.col] = -1
}
newChessBorad[row][column] = 1
return newChessBorad
}
func solve(chessboard:ChessBoard, queens: Int) {
if queens == 0 {
//Goal
result.insert(chessboard)
}
for row in 0..<n {
for col in 0..<n {
//Choices
if chessboard[row][col] == 0 {
//Constraints
let new = placeQuees(chessboard: chessboard, row: row, column: col)
solve(chessboard: new, queens: queens - 1)
}
}
}
}
solve(chessboard: Array(repeating: Array(repeating: 0, count: n), count: n), queens: n)
return result.map {
//chessboard
$0.map {
//row to string
$0.reduce("") { string,value in
if value == 1 {
return string + "Q"
} else {
return string + "."
}
}
}
}
}
但是时间有限。所以我想知道我的解决方案是否使用Backtracking?出了什么问题,如何改善解决方案,如何解决回溯问题?什么定义了回溯?
非常感谢。
答案 0 :(得分:1)
您的解决方案正在回溯。当无法找到放置女王的可用空间(chessboard[row][col] == 0
)时,它将回溯。由于它正在查找所有可能的解决方案,因此在找到解决方案并将其插入result
后也会回溯。
您的解决方案是在每次致电solve
时尝试过多的试用职位。请注意,任何给定的行上只能有一个女王。因此,solve
可以通过在每次对solve
的调用中仅将皇后放在单个行中来提高工作效率。在第一次致电solve
时,请尝试将皇后放在row 0
上。然后,您将只考虑n
个可能的展示位置,而不是n * n
个。在第二次致电solve
时,尝试将女王放在row 1
上。当前row
可以计算为n
减去剩余的皇后数量或n - queens
。
稍加修改,您的代码就会运行得更快,并在提交给LeetCode时成功通过:
func solve(chessboard:ChessBoard, queens: Int) {
if queens == 0 {
//Goal
result.insert(chessboard)
}
else {
let row = n - queens
for col in 0..<n {
//Choices
if chessboard[row][col] == 0 {
//Constraints
let new = placeQuees(chessboard: chessboard, row: row, column: col)
solve(chessboard: new, queens: queens - 1)
}
}
}
}