回溯算法的经典应用 —— LeetCode 51.N皇后问题(Kotlin) - Go语言中文社区

回溯算法的经典应用 —— LeetCode 51.N皇后问题(Kotlin)


head

separatorLine

题目描述

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

separatorLine

推荐阅读:
LeetCode题解,使用kotlin语言,欢迎star:

注:本文排版仿照LeetCode官方公众号,侵删

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/AlpinistWang/article/details/88287541
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 01:28:09
  • 阅读 ( 1555 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢