リリース・改善中
Algorithm
バックトラッキングは解を一手ずつ組み立て、制約に反した選択を取り消して戻る探索手法で、順列・N-Queens・数独などを枝刈りで効率よく解きます。
バックトラッキングは、状態空間木を深さ優先で探索しながら答えを一手ずつ埋めていき、それまでの選択が制約に反した時点で一つ前の段階に戻って別の選択を試す手法です。コードは、候補を選ぶ(選択)、再帰で下りる(探索)、戻ってきたら選んだものを取り消す(取り消し)という三つの動作の繰り返しでできています。
すべての候補を最後まで作ってから検査する全探索と違い、見込みのない枝を途中で切り落とすため、同じ問題を桁違いに少ない試行で解けることが多くあります。順列や組み合わせの列挙、N-Queens、数独、グラフ彩色といった制約充足問題の定番の解法であり、正規表現エンジンや SAT ソルバーの土台でもあるため、コーディング面接でも実務でもよく出会います。
まず部分集合や順列のような枝刈りのない列挙問題で選択・探索・取り消しの型を身につけ、次に N-Queens と数独で制約チェックと枝刈りを練習するのがおすすめです。そのうえで訪問ノード数を実際に数えて枝刈りの効果を確かめ、同じ問題を動的計画法と比べて、どの手法をいつ選ぶかを整理しておきましょう。
空の状態を根、選択一つを辺と見ると、すべての候補が木の経路になり、バックトラッキングはこの木を深さ優先でたどります。
部分解に候補を加えて再帰で下り、戻ったら取り除くパターンで、一つのリストをすべての枝で共有します。
現在の部分解が解につながらないとわかれば、その下の枝をまとめて飛ばし、指数的な探索空間を実際にはずっと小さくします。
使用済みの列・対角線・行・ブロックを集合や配列で管理すれば、新しい選択が規則に反するかを定数時間で判定できます。
permutations は used 配列で選択済みの要素を除外しながら、選択・探索・取り消しですべての順列を作り、完成した経路は path[:] でコピーして保存します。n_queens は列と二つの対角線(row - c、row + c)を集合で管理し、攻撃されるマスをすぐに飛ばして解の数を数えます。python backtracking.py で実行すると [1, 2, 3] の順列 6 個と 8-Queens の解の数 92 が出力されます。
backtracking.py
def permutations(items):
result, path = [], []
used = [False] * len(items)
def backtrack():
if len(path) == len(items):
result.append(path[:]) # store a copy of the full path
return
for i, x in enumerate(items):
if used[i]:
continue
used[i] = True # choose
path.append(x)
backtrack() # explore
path.pop() # unchoose
used[i] = False
backtrack()
return result
def n_queens(n):
cols, diag, anti = set(), set(), set()
def place(row):
if row == n:
return 1
count = 0
for c in range(n):
if c in cols or row - c in diag or row + c in anti:
continue # prune: square is attacked
cols.add(c); diag.add(row - c); anti.add(row + c)
count += place(row + 1)
cols.remove(c); diag.remove(row - c); anti.remove(row + c)
return count
return place(0)
print(permutations([1, 2, 3]))
print(n_queens(8)) # 92
python backtracking.pyインストールから バックトラッキング の中心となる考え方まで、6 章で順を追って学びます。
バックトラッキング について質問し、経験を共有し、意見を交わす場所です。
まだディスカッションはありません。最初の話題を始めましょう。
コメント 0件
ログイン · ログインするとコメントできます。
最初のコメントを書いてみましょう。