Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

バックトラッキング

バックトラッキング(Backtracking) は、再帰的に候補を構築しながら、制約を満たさないと判明した時点で引き返す(バックトラック)全探索の手法

純粋な全列挙と異なり、枝刈り(pruning) によって探索空間を大幅に削減できる

solve(状態):
    if 完成:
        結果を記録
        return
    for 候補 in 次の選択肢:
        if 候補が制約を満たす:
            状態に候補を追加
            solve(次の状態)      # 再帰
            状態から候補を除去   # バックトラック

例1: 部分和問題

整数のリストから、合計が目標値 target になる組み合わせをすべて列挙する

例2: N-クイーン問題

N×NN \times N のチェスボードに、NN 個のクイーンをお互いに攻撃し合わない配置をすべて列挙する

  • 各行に必ず1つのクイーンを置く

  • 列・斜めが重複しないかをチェックして枝刈り

例3: 順列生成(重複なし)

itertools.permutations と同じ結果を、バックトラッキングで実装する例

枝刈りの重要性

バックトラッキングの効率は枝刈りの質で決まる

問題枝刈りなし枝刈りあり
8-クイーン88=16,777,2168^8 = 16{,}777{,}21692解(探索ノード数は大幅削減)
部分和2N2^N目標超過で早期打ち切り

枝刈りのパターン:

  • 実行可能性チェック: 現在の部分解が制約を満たさないなら即リターン

  • 上界チェック: これ以上改善できないなら打ち切り(Branch and Bound)

  • 対称性の除去: 等価な解を同一視して探索数を削減