N皇后问题(C++实现和函数式编程实现)
题意
在 N * N 的方格棋盘放置了 N 个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。求出有多少种合法的放置方法。
C++实现(位运算优化)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int MAX, ans;
void dfs(int row, int ld, int rd) {
if(row == MAX) {
ans++;
return;
}
int pos = (MAX & ~(row | ld | rd));
while(pos) {
int p = (pos & -pos); // 找到二进制位最低位的 1 的位置
dfs(row | p, (ld | p) << 1, (rd | p) >> 1);
pos -= p;
}
}
int main() {
while(cin >> n && n) {
if(n == 1) cout << 1 << endl;
else if(n < 4) cout << 0 << endl;
else {
ans = 0;
MAX = (1 << n) - 1;
dfs(0, 0, 0);
cout << ans << endl;
}
}
return 0;
}
scheme实现
用的 r5rs 版本,所以许多函数需要自己定义。
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
(define (enumerate-interval low high)
(if (> low high)
nil
(cons low (enumerate-interval (+ low 1) high))))
(define (flatmap proc seq)
(accumulate append nil (map proc seq)))
(define (filter f? seq)
(define (iter result seq)
(cond ((null? seq) result)
((f? (car seq)) (iter (cons (car seq) result) (cdr seq)))
(else (iter result (cdr seq)))))
(iter '() seq))
(define (queens board-size)
(define empty-board '())
(define (safe? k positions)
(define (iter-check row-of-new-queen rest-of-queens i)
(if (= i k)
#t
(let ((row-of-current-queen (car rest-of-queens)))
(if (or (= row-of-new-queen row-of-current-queen)
(= row-of-new-queen (+ row-of-current-queen i))
(= row-of-new-queen (- row-of-current-queen i)))
#f
(iter-check row-of-new-queen
(cdr rest-of-queens )
(+ i 1))))))
(iter-check (car positions) (cdr positions) 1))
(define (adjoin-position new-row rest-of-queens)
(cons new-row rest-of-queens))
(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 rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
(define (count l)
(if (null? l)
0
(+ (count (cdr l)) 1)))
(count (queens 8))
flatmap 函数把产生的新皇后的位置加入到每个已经符合条件的格局(已经摆放好的皇后的状态)中,这里 rest-of-queens 是在前 k - 1 列放置 k - 1 个皇后的一种方式,使用 map 函数映射 [1, n],adjoin-position 函数的作用就是把 [1, n] 的值当作新皇后的行的位置加入到某一个格局中,用 filter 函数过滤掉存在冲突的格局。