暴力法、窮舉搜尋與回溯

列舉所有排列(enumerating all permutations)

有時答案不在於選哪些,而在於以什麼順序排。n 位賓客圍桌而坐、n 個工作在一台機器上排程、決定走訪 n 座城市的路線——每一個都是順序的選擇,而 n 件相異物品的所有順序之全體,就是排列的集合。它恰有 n! 個:第一個位置有 n 種選擇,第二個有 n-1 種,第三個 n-2 種,依此遞減到 1。

把它們全部生成的自然方式,是「一次固定一個位置」的遞迴。要列出一個集合的所有排列,就依次挑每一個可用元素當第一個,然後遞迴列出其餘元素的所有排列,再把你的選擇接在前面。基底情況是空集,它唯一的排列是空序列。這會把每個排列恰走訪一次:深度 1 分 n 岔,深度 2 其餘 n-1 岔,而乘積 n * (n-1) * ... * 1 = n! 正是葉子的數目,所以不漏也不重。許多語言還提供 next-permutation 程序,給它一個順序就能就地算出字典序中的下一個,於是你能用一個簡單迴圈掃過全部 n! 個順序。

排列列舉是旅行推銷員問題、最佳工作排序、指派問題在更聰明方法登場之前的暴力解法。它的代價殘酷:n! 比任何指數 2^n 都長得更快,所以光是 n = 13 就有超過六十億個順序,n = 20 則完全無望。正是這份陡峭,讓排列問題成為分支定界、在子集合上做動態規劃(解 TSP 的 Held-Karp 法跑 O(2^n n^2),遠勝 n!)與啟發式方法的展示舞台。

{1, 2, 3} 的排列是 123、132、213、231、312、321——恰好 3! = 6 個。把第一個固定為 1 得到區塊 123、132(即 {2,3} 的兩種排序);固定為 2 得到 213、231;固定為 3 得到 312、321。每個順序出現一次。

第一格固定有 n 種、其餘遞迴:n! 個葉子恰是那些排列,不漏也不重。

n! 超過 2^n:大約到 n = 13 就已破十億個順序,所以排列暴力法只在 n 為個位數左右時實用——再大就得靠 Held-Karp 動態規劃、分支定界或啟發式方法。

又称
permutation enumerationordering enumeration枚舉排列全排列