八皇后问题

9 篇文章 0 订阅

八皇后问题

问题介绍

在一个 8×8 的国际象棋棋盘上摆放8个皇后,使她们任意两个相互不在对方的射程内。

参见百度百科,八皇后问题

思路

有两个主要问题:

  • 判断皇后是否安全
  • 以某种顺序考虑所有情况

动态地看,新加入的皇后不会影响已有皇后的攻击性。换句话说,原来相安无事的两个皇后不会因为新加入的皇后而变得相互攻击,新的皇后也不会改变原来皇后的威慑区域。正是本问题的这个特性,让我们在加入新皇后时可以单独考虑各个原有皇后,依次检查其是否与新皇后发生冲突。并且,在添加新皇后之后也不需要重新检查原有皇后。

编程

Scheme 递归

(define empty-board '())

(define (adjoin-position new-row k rest-queens)
  (cons new-row rest-queens))


(define (safe? k positions)
  (define queen-row (car positions))
  (define (iter delta rest-queens)
    (if (null? rest-queens)
        true
        (if (or (= queen-row (car rest-queens))
                (= (abs (- queen-row (car rest-queens))) delta))
            false
            (iter (+ delta 1) (cdr rest-queens)))))
  (iter 1 (cdr positions)))


(define (queens board-size)
  (define (queen-cols k)
    (if (= k 0)
        (list empty-board)
        (filter
         (lambda (positions) (safe? k positions))
         (flatmap
          (lambda (rest-of-queens)
            (map (lambda (new-row)
                   (adjoin-position new-row k rest-of-queens))
                 (enum-interval 0  (- board-size 1))))
          (queen-cols (- k 1))))))
  (queen-cols board-size))
(length (queens 8))
> 92

Python

穷举
from itertools import *

def safe(new_queen, rest_queens):
    for delta, queen in enumerate(rest_queens, 1):
        if new_queen == queen or abs(new_queen - queen) == delta:
            return False
    return True

def all_safe(queens):
    return all(safe(queens[i], queens[i + 1:]) for i in range(len(queens)))

results = []

for queens in product(range(8), repeat=8):
    if all_safe(queens):
        results += [queens]

len(results)
> 92
递归
class Solution:

    def totalNQueens(self, n: int) -> int:

        def starmap(func, items):
            res = []
            for item in items:
                res += func(item)
            return res

        def safe(chessboard, i):
            for col, chess in enumerate(chessboard):
                if i == chess or abs(i - chess) == len(chessboard) - col:
                    return False
            return True
        
        def extend(chessboard, n):
            res = []
            for i in range(n):
                if safe(chessboard, i):
                    res.append(chessboard + [i])
            return res

        def r(coln):
            if coln == 0:
                return [[i] for i in range(n)]
            else:
                return starmap(lambda case: extend(case, n), r(coln - 1))
        
        return len(r(n - 1))

关于循环的顺序

递归解法中,务必将递归调用放在外层循环,让这个费时的调用只计算一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值