数学建模社区-数学中国

标题: 排列树的回溯搜索解决n皇后问题 [打印本页]

作者: 2744557306    时间: 2023-12-22 16:28
标题: 排列树的回溯搜索解决n皇后问题
这是一个MATLAB实现的N皇后问题,这是一个经典的组合问题。其目标是在一个N×N的棋盘上放置N个皇后,使得它们之间互不攻击。提供的代码使用了递归回溯的方法来找到N皇后问题的所有解决方案。; X+ T8 \  B! w" N# v: J7 ?! l  C, }
让我们逐步解释这段代码:% ~0 B7 ^( ?% U: w) Q0 ^
function [chess, main, deputy, number] = justtry(i, n, chess, main, deputy, number)9 n* C; `( e; q4 d5 f& M

) p- ~) p! y# L6 w: s这定义了一个名为justtry的函数,它接受六个参数:当前行数i,棋盘大小n,当前皇后的排列chess,主对角线和副对角线的状态(main和deputy),以及解的数量number。
9 H) I6 M, h- `if i == 9
1 e7 Q6 e. s& O$ @- ^. p    number = number + 1;
' h9 W/ r1 \' F9 A$ K- B( g    chess
6 P( _/ s. o, V9 _0 _else
6 @% s* t; b+ b  G  N( t    for k = i:86 j7 |: P0 {' d5 X6 I
        if main(i - chess(k) + n) == 0 && deputy(i + chess(k) - 1) == 0
: X# V! H1 M' G4 \! k6 ?! R6 _$ g. F8 C, T
这检查是否已经到达第9行。如果是这样,它会递增解的数量(number)并显示当前皇后在棋盘上的排列。否则,它进入一个从当前行(i)到8的循环。' X& o* n1 d# {8 j" ]
嵌套的if语句检查当前棋盘位置是否有效(即没有皇后互相威胁)。如果条件满足,它将继续放置皇后。
$ f& r8 ]) n/ Q! `            t = chess(k); % 交换位置1 P0 W# i6 s6 O# I( _+ j
            chess(k) = chess(i);
- H" |! c6 d  W5 k2 x( \            chess(i) = t;
. `1 e/ M; U. X0 b: q, [
1 I2 J$ y5 b1 ?3 k            main(i - chess(k) + n) = 1;
7 k2 ^" t5 E& X" l/ r4 R            deputy(i + chess(k) - 1) = 1;
2 D& w$ b* p9 I# Z) M$ P4 b5 }
& }  N. n+ J! N# U" H- J, @) \- j            [chess, main, deputy, number] = justtry(i + 1, n, chess, main, deputy, number); % 递归调用
" V/ v% o1 b, J  j! s- s
/ y  n' F+ A1 M+ t+ H, T            t = chess(k); % 回溯" n$ b, i- J! _5 q
            chess(k) = chess(i);  k6 {0 i/ |- d8 l
            chess(i) = t;
$ ?/ R- W( [' Q2 ^9 g' o( \
. r' P9 ]8 K7 n. s7 l7 ]; ]( h            main(i - chess(k) + n) = 0;' ^+ y& t0 G$ i6 |
            deputy(i + chess(k) - 1) = 0;
7 n9 L( k1 M2 H  u. P: G/ g, t7 b8 c& x6 ]
这部分是回溯算法的核心。它交换皇后的位置,更新对角线的状态,对下一行进行递归调用,然后通过恢复原始状态进行回溯。
6 ^0 I- ]% b2 ~' x        end
9 p/ p2 G' w0 }    end# M' U5 H+ U# D# W! q4 v4 ^) E3 [
end
2 M5 d& T7 ]% A3 Z
. p8 ]: L  d8 }+ M* y这结束了循环和函数。如果i不是9,循环将继续到下一行。" U  }+ F8 J+ B# W4 }
clear all$ q/ m0 O0 x2 k7 t  {( A. v
clc- y9 n& L1 H  g! b8 s
. e# d# g) h% u% E1 u" p7 B
这些命令清除工作区和命令窗口。
! V4 w7 t- e- U; @, A* D6 Wn = 8;
% ?8 U( U3 e) U* J1 K; L9 O8 G' ~chess = zeros(1, n);# g& d1 H' y  x9 ^7 @
for i = 1:n, A7 q- x# R& v: w6 O* R
    chess(i) = i;
; t* a4 D% x% E& ^9 p4 iend
) b1 X" n# ?; D6 V0 H  P& c8 w4 Y: p; F8 ]% F4 x% V$ F/ t& G: k
这初始化了一个带有皇后的第一行的棋盘。
, T3 F6 z. S4 L% a/ K1 [main = zeros(1, 2 * n - 1); % 记录主对角线的使用情况2 r- l2 P8 ^9 a  ~7 z1 [0 f
deputy = zeros(1, 2 * n - 1); % 记录副对角线的使用情况
& P( b0 m5 j' t3 v$ l2 cnumber = 0;6 _$ v) \3 x: |2 v+ B6 }
[chess, main, deputy, number] = justtry(1, n, chess, main, deputy, number);3 A9 Q5 k* d- }( Y2 U4 {2 v
% ^" \& ]4 p7 F, w: j
这初始化了数组以跟踪主对角线和副对角线的情况,并通过调用justtry开始了递归回溯。整个过程将探索在8x8棋盘上所有可能的皇后排列,并打印每个有效排列以及解的总数。
4 Z% r& A0 p0 B+ c8 a3 f  k" y- ]+ K6 o6 [

  i6 ~5 R8 ^2 @. {5 d, W" i- f




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5