You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于回溯算法求解N×N棋盘最小白皇后覆盖黑棋子问题咨询

回溯算法求解最少白皇后覆盖黑棋子:候选皇后的判断与选择逻辑

嘿,针对你这个问题,咱们可以从回溯的核心逻辑、状态维护和剪枝优化这几个维度来拆解,确保能高效找到最少的皇后数量:


1. 先理清楚回溯的核心状态

首先你得在回溯过程中维护三个关键状态,这是判断的基础:

  • 已选皇后列表:记录当前已经选了哪些候选位置的皇后
  • 已覆盖黑棋集合:用一个哈希集或布尔数组标记哪些黑棋已经被攻击到(避免重复计算)
  • 当前皇后计数:用来和当前找到的最优解对比,及时剪枝

2. 候选皇后的选择优先级(优化关键)

遍历候选皇后的时候,别傻乎乎按顺序来,优先选能覆盖更多未被覆盖黑棋的候选位置。这种贪心+回溯的结合能大幅减少递归分支,更快逼近最优解——毕竟选一个能覆盖一堆漏网黑棋的皇后,比选只能覆盖一两个的效率高多了。

3. 判断是否纳入当前候选皇后的核心规则

当你考虑某个候选皇后时,按这两步来判断:

  • 第一步:先看这个皇后能覆盖的黑棋里,有没有还没被已选皇后覆盖的新目标。如果它覆盖的所有黑棋都已经被之前选的皇后搞定了,直接跳过——选它只会平白增加皇后数量,完全不符合“最少”的要求。
  • 第二步:如果它能覆盖新的黑棋,那就可以尝试纳入解:
    1. 把它覆盖的所有未被覆盖的黑棋标记为已覆盖
    2. 将这个皇后加入已选列表
    3. 递归进入下一层,处理剩下的未被覆盖黑棋
    4. 回溯操作:移除这个皇后,把标记的黑棋恢复为未覆盖(回到之前的状态,尝试其他可能)

4. 必须做的剪枝操作(不然会慢到离谱)

  • 如果当前用的皇后数量已经等于甚至超过了当前找到的最优解,直接停止这个分支的递归——再往下走也不可能得到更优的结果,纯浪费时间。
  • 一旦所有黑棋都被覆盖了,立刻更新全局最优解(比如当前用了3个皇后,之前的最优解是5,那就把最优解改成3)。

5. 终止条件

要么是所有黑棋都被覆盖(记录当前皇后数,更新最优解),要么是所有候选皇后都遍历完了,直接返回当前的最优结果。

给你贴个伪代码示例,更直观:

# 全局最优解,初始设为候选皇后总数(最坏情况)
min_required = len(candidate_queens)
# 提前预处理:每个候选皇后对应的覆盖黑棋集合
queen_to_black = {pos: attacked_black_set for pos, attacked_black_set in zip(candidate_queens, precomputed_covers)}
# 所有黑棋的总集合
total_black = set(all_black_pieces)

def backtrack(selected, covered, count):
    global min_required
    # 剪枝:当前数量已经不优于已知最优,直接返回
    if count >= min_required:
        return
    # 所有黑棋都被覆盖,更新最优解
    if covered == total_black:
        min_required = count
        return
    # 按覆盖未被覆盖黑棋的数量从多到少排序,优先选效率高的
    for queen in sorted(candidate_queens, key=lambda q: len(queen_to_black[q] - covered), reverse=True):
        new_covered = queen_to_black[queen] - covered
        if not new_covered:
            continue  # 没有新覆盖,跳过
        # 选择这个皇后,进入下一层递归
        backtrack(selected + [queen], covered.union(new_covered), count + 1)

# 初始调用:无皇后选中,无黑棋被覆盖,计数为0
backtrack([], set(), 0)

说白了,核心就是只选能带来新覆盖价值的候选皇后,再通过剪枝和排序优化砍掉无效分支,这样就能高效找到最少的皇后数量啦。

内容的提问来源于stack exchange,提问作者user13353974

火山引擎 最新活动