題目描述
N皇后 ← 點擊鏈接進入題目
n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。
上圖爲 8 皇后問題的一種解法。
給定一個整數 n,返回所有不同的 n 皇后問題的解決方案。
每一種解法包含一個明確的 n 皇后問題的棋子放置方案,該方案中 ‘Q’ 和 ‘.’ 分別代表了皇后和空位。
示例:
輸入: 4
輸出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解釋: 4 皇后問題存在兩個不同的解法。
解決方案
class Solution {
// 記錄總皇后數
private var totalQueues = 0
// 記錄已經放置的皇后位置
private lateinit var queens: IntArray
// 記錄可行的方案
private lateinit var solutions: MutableList<List<String>>
fun solveNQueens(n: Int): List<List<String>> {
solutions = mutableListOf()
totalQueues = n
queens = IntArray(n)
backTrack(0)
return solutions
}
/**
* 放置第 current 個皇后
*/
private fun backTrack(current: Int) {
// 如果已經放下了最後一個皇后,表明此方案可行,記錄此方案
if (current == totalQueues) {
val queenList = mutableListOf<String>()
for (i in 0 until totalQueues) {
val stringBuilder = StringBuilder()
for (j in 0 until totalQueues)
stringBuilder.append(if (queens[i] == j) "Q" else ".")
queenList.add(stringBuilder.toString())
}
solutions.add(queenList)
return
}
// 還未到最後一行,嘗試放置皇后
for (position in 0 until totalQueues) {
queens[current] = position
// 如果能放在此位置,繼續放置下一個皇后
if (canPlace(current)) backTrack(current + 1)
// 否則繼續循環,嘗試放置在另一個位置。這裏是回溯的精髓,有一個回到上一步的操作
}
}
/**
* 判斷皇后能否放在此位置
*/
private fun canPlace(position: Int): Boolean {
// 判斷是否與之前放置的皇后衝突
for (before in 0 until position) {
if (queens[before] == queens[position]
|| Math.abs(queens[position] - queens[before]) == Math.abs(position - before)
)
return false
}
return true
}
解題思路
1.用queens[current]=position表示第current個皇后放在第current行,第position列。
2.由於每一行上只有一個皇后,所以皇后在橫向不會衝突。
3.先嚐試將皇后放在position位置上,再判斷這個皇后放在這裏會不會和之前的皇后衝突。判斷方法爲:
if (queens[before] == queens[position]
|| Math.abs(queens[position] - queens[before]) == Math.abs(position - before))
return false
(1)如果queens[before] == queens[position],表示豎向衝突
(2)如果Math.abs(queens[position] - queens[before]) == Math.abs(position - before)),表示斜線上衝突。
4.如果這個皇后沒有和之前放置的所有皇后衝突,表示此皇后可以放在這裏,繼續放下一個皇后。
5.如果這個皇后和之前放置的皇后衝突,則回到上一步,嘗試將此皇后放置在下一個position位置上。這個回到上一步的操作就是回溯算法的精髓。
6.如果放完所有皇后都沒有衝突,表示此方案可行。根據queens數組拼接答案即可。
參考文章:回溯算法經典應用之—N皇后問題 (Java):https://blog.csdn.net/qianhaifeng2012/article/details/52300829
推薦閱讀:
LeetCode題解,使用kotlin語言,歡迎star:
注:本文排版仿照LeetCode官方公衆號,侵刪