题目描述
先确认输入、输出、限制条件,再判断能不能把暴力解法优化掉。
思路解析动画文字版
核心思路:逐行往下放:在当前行从左到右挨个试列,放之前检查这一列、左上斜线、右上斜线上有没有已放的皇后——有冲突就跳过这格试下一列;一整行都没法放,就退回上一行把那儿的皇后挪到下一个可行列(这就是回溯)。
空棋盘 · 从第 0 行开始:棋盘全空。我们从最上面的第 0 行开始,在这一行从最左列(列 0)往右挨个尝试,找到一个安全列就落子,然后下到第 1 行重复,直到 4 行都放满就是一个完整方案。
第 0 行 · 尝试列 0:轮到第 0 行。橙色格 (行0,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 0 行 · 列 0 安全,落子 ♛:(行0,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
第 1 行 · 尝试列 0:轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 0 冲突 ✗:红格说明 (行1,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 1:轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 1 冲突 ✗:红格说明 (行1,列1) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 2:轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 2 安全,落子 ♛:(行1,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 冲突 ✗:红格说明 (行2,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 冲突 ✗:红格说明 (行2,列1) 不安全:它和第 1 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 冲突 ✗:红格说明 (行2,列2) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 冲突 ✗:红格说明 (行2,列3) 不安全:它和第 1 行(列2)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 1 行列 2 的皇后:第 1 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
第 1 行 · 尝试列 3:轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 3 安全,落子 ♛:(行1,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 冲突 ✗:红格说明 (行2,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 安全,落子 ♛:(行2,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
第 3 行 · 尝试列 0:轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 0 冲突 ✗:红格说明 (行3,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 1:轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 1 冲突 ✗:红格说明 (行3,列1) 不安全:它和第 1 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 2:轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 2 冲突 ✗:红格说明 (行3,列2) 不安全:它和第 2 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 3:轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 3 冲突 ✗:红格说明 (行3,列3) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 2 行列 1 的皇后:第 2 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 冲突 ✗:红格说明 (行2,列2) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 冲突 ✗:红格说明 (行2,列3) 不安全:它和第 1 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 1 行列 3 的皇后:第 1 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
回溯 · 撤掉第 0 行列 0 的皇后:第 0 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
第 0 行 · 尝试列 1:轮到第 0 行。橙色格 (行0,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 0 行 · 列 1 安全,落子 ♛:(行0,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
第 1 行 · 尝试列 0:轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 0 冲突 ✗:红格说明 (行1,列0) 不安全:它和第 0 行(列1)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 1:轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 1 冲突 ✗:红格说明 (行1,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 2:轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 2 冲突 ✗:红格说明 (行1,列2) 不安全:它和第 0 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 3:轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 3 安全,落子 ♛:(行1,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 安全,落子 ♛:(行2,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
第 3 行 · 尝试列 0:轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 0 冲突 ✗:红格说明 (行3,列0) 不安全:它和第 2 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 1:轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 1 冲突 ✗:红格说明 (行3,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 2:轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 2 安全,落子 ♛:(行3,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 4 行,继续从列 0 开始试。
★ 找到第 1 个完整方案:4 行全部放满且谁也吃不到谁——记下这个方案(每行皇后的列号是 [1, 3, 0, 2])。方案数 +1。然后回溯:撤掉最后放的皇后,回上一行继续试别的列,看还有没有别的摆法。
回溯 · 撤掉第 3 行列 2 的皇后:第 3 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 3 行继续向右试下一列;本行列都试完就再退回上一行。
第 3 行 · 尝试列 3:轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 3 冲突 ✗:红格说明 (行3,列3) 不安全:它和第 1 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 2 行列 0 的皇后:第 2 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 冲突 ✗:红格说明 (行2,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 冲突 ✗:红格说明 (行2,列2) 不安全:它和第 1 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 冲突 ✗:红格说明 (行2,列3) 不安全:它和第 0 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 1 行列 3 的皇后:第 1 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
回溯 · 撤掉第 0 行列 1 的皇后:第 0 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
第 0 行 · 尝试列 2:轮到第 0 行。橙色格 (行0,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 0 行 · 列 2 安全,落子 ♛:(行0,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
第 1 行 · 尝试列 0:轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 0 安全,落子 ♛:(行1,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 冲突 ✗:红格说明 (行2,列0) 不安全:它和第 0 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 冲突 ✗:红格说明 (行2,列1) 不安全:它和第 1 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 冲突 ✗:红格说明 (行2,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 安全,落子 ♛:(行2,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
第 3 行 · 尝试列 0:轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 0 冲突 ✗:红格说明 (行3,列0) 不安全:它和第 1 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 1:轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 1 安全,落子 ♛:(行3,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 4 行,继续从列 0 开始试。
★ 找到第 2 个完整方案:4 行全部放满且谁也吃不到谁——记下这个方案(每行皇后的列号是 [2, 0, 3, 1])。方案数 +1。然后回溯:撤掉最后放的皇后,回上一行继续试别的列,看还有没有别的摆法。
回溯 · 撤掉第 3 行列 1 的皇后:第 3 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 3 行继续向右试下一列;本行列都试完就再退回上一行。
第 3 行 · 尝试列 2:轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 2 冲突 ✗:红格说明 (行3,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 3:轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 3 冲突 ✗:红格说明 (行3,列3) 不安全:它和第 2 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 2 行列 3 的皇后:第 2 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
回溯 · 撤掉第 1 行列 0 的皇后:第 1 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
第 1 行 · 尝试列 1:轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 1 冲突 ✗:红格说明 (行1,列1) 不安全:它和第 0 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 2:轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 2 冲突 ✗:红格说明 (行1,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 3:轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 3 冲突 ✗:红格说明 (行1,列3) 不安全:它和第 0 行(列2)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 0 行列 2 的皇后:第 0 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
第 0 行 · 尝试列 3:轮到第 0 行。橙色格 (行0,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 0 行 · 列 3 安全,落子 ♛:(行0,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
第 1 行 · 尝试列 0:轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 0 安全,落子 ♛:(行1,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 冲突 ✗:红格说明 (行2,列0) 不安全:它和第 1 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 冲突 ✗:红格说明 (行2,列1) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 安全,落子 ♛:(行2,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
第 3 行 · 尝试列 0:轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 0 冲突 ✗:红格说明 (行3,列0) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 1:轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 1 冲突 ✗:红格说明 (行3,列1) 不安全:它和第 2 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 2:轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 2 冲突 ✗:红格说明 (行3,列2) 不安全:它和第 1 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 3 行 · 尝试列 3:轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 3 行 · 列 3 冲突 ✗:红格说明 (行3,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 2 行列 2 的皇后:第 2 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 冲突 ✗:红格说明 (行2,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 1 行列 0 的皇后:第 1 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
第 1 行 · 尝试列 1:轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 1 安全,落子 ♛:(行1,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
第 2 行 · 尝试列 0:轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 0 冲突 ✗:红格说明 (行2,列0) 不安全:它和第 1 行(列1)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 1:轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 1 冲突 ✗:红格说明 (行2,列1) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 2:轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 2 冲突 ✗:红格说明 (行2,列2) 不安全:它和第 1 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 2 行 · 尝试列 3:轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 2 行 · 列 3 冲突 ✗:红格说明 (行2,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 1 行列 1 的皇后:第 1 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
第 1 行 · 尝试列 2:轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 2 冲突 ✗:红格说明 (行1,列2) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
第 1 行 · 尝试列 3:轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
第 1 行 · 列 3 冲突 ✗:红格说明 (行1,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
回溯 · 撤掉第 0 行列 3 的皇后:第 0 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
搜索结束 · 4 皇后共 2 个方案:所有行的所有列都试遍、所有分支都回溯完,搜索结束。4×4 棋盘上让 4 个皇后互不攻击,一共只有 2 种摆法。N 越大方案越多,但搜索套路完全一样:逐行放、放前判三向冲突、无路可走就回溯。
边界:N=1 有 1 个方案(孤零零一个皇后);N=2 和 N=3 无解(怎么放都互相攻击,res 为空);N=4 是 2 个;从 N=4 起才有解。代码对这些都自然成立,无需特判。
高频追问:问:怎么把 O(N) 的 valid 检查降到 O(1)?答:用三个布尔/集合分别记「占用的列、占用的主对角线 row-col、占用的副对角线 row+col」,放子时打标、撤子时清标,判冲突直接查表。问:只要方案个数(LC 52)怎么办?答:同一套回溯,把收集结果改成计数器 +1 即可。
参考代码
def solveNQueens(n): res, cols = [], [-1] * n def valid(row, col): for r in range(row): c = cols[r] if c == col or r - c == row - col \ or r + c == row + col: return False return True def dfs(row): if row == n: res.append(cols[:]); return for col in range(n): if valid(row, col): cols[row] = col dfs(row + 1) cols[row] = -1 dfs(0) return res复杂度
易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
解数独
LeetCode 37 · 困难 · 沿着 回溯 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题