写 N 皇后

补全 queens:一行放一个,放之前先用 ok 查一遍,放不下就跳过。输出 4 皇后的解数。

开始练习 →

四种规模各有几个解

把 n = 4、5、6、7 各跑一遍,把四个解数拼起来输出。 (这四个数不是递增的——留意 6 比 5 还少。)

开始练习 →

⚠️ 剪枝在 N 皇后上省了多少

写两个版本跑 n = 5: 剪枝版:放之前就用 ok 查 不剪枝版:把 5 行全铺满,最后才逐对检查 输出四样:剪枝解数 / 不剪枝解数 / 剪枝结点数 / 不剪枝结点数。

开始练习 →

⚠️ 为什么要存 list(path) 而不是 path

记录一个解时要写 res.append(list(path)),因为【0】。

开始练习 →

撤销要撤哪些东西

回溯的撤销要覆盖【0】。

开始练习 →

⚠️ 存引用会得到什么

这个版本记解时写的是 res.append(path)(没有转成副本)。运行它,看解的个数和第一个解的长度: def perm_ref(a): res = [] path = [] used = [False] *

开始练习 →

漏了 path.pop() 会剩几个解

这个版本撤销时只改回了 used,忘了把 path 弹出来。运行它: def perm_nopop(a): res = [] path = [] used = [False] * len(a) def dfs

开始练习 →

把路径记对

补全 perm:记解时存副本,撤销时 used 和 path 两样都撤。 输出解的个数和第一个解。

开始练习 →

⚠️ 存引用和存副本,一起跑

写两个版本:一个 res.append(path),一个 res.append(list(path))。 把两者第一个解的长度拼起来输出(存引用的在前)。

开始练习 →

⚠️ 两种漏撤销,症状一模一样

写三个版本跑 [1, 2, 3]: 漏了 path.pop() 漏了 used[i] = False 两样都撤销的正确版 把三个解的个数拼起来输出(按上面的顺序)。

开始练习 →