bit全探索

bit全探索について学びます。

bit全探索とは

探索をbitを用いて行うことです。 あるN個のものから、選択する・しないを0か1で表すことで、全てのパターンを列挙することができます。 例えば、N=4のとき、24=16パターンの列挙に、0000〜1111の2進数を用います。

基本的な考え方

全探索と言っているので、全てのパターンを網羅的に調べ上げます。 この時、N=4であれば、16パターンになりますが、10進数の0〜15を2進数に直します。 そこで、どのビットが1になっているかを判定することで、4種類の全ての状態を網羅できます。

実装方法

まず、入力Nに対して、2N回のループを回します。(以下、pythonでの実装となります。)

for i in range(2 ** N)

次に、上記のループで回している数について、2進数での各bitが1になっているかをシフト演算を用いて調査します。

for j in range(N):
    #ここがシフト演算
    if (i >> j) & 1:
        #何かする

何をしているのか。
例えばN=3を例にとってみましょう。N=3の場合、23は以下の8パターンがあります。

10進数 2進数
0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111

このうち、5の(101)に注目してみましょう。
0〜2ビット右シフト演算をすると、結果は以下のようになります。
101 → 101
101 → 010
101 → 001
一番下位桁が1になる場合に、その桁が表す選択肢を何か実行すれば良いわけです。
ここまでをまとめてみます。
例として、3種類の果物の選び方を全て列挙してみます。

#bit全探索
n = 3

fruits = ["みかん", "りんご", "ぶどう"]
for i in range(2 ** n):
    result = []
    for j in range(n):
        if (i >> j) & 1:
            result.append(fruits[j])
    print(result)

結果

[]
['みかん']
['りんご']
['みかん', 'りんご']
['ぶどう']
['みかん', 'ぶどう']
['りんご', 'ぶどう']
['みかん', 'りんご', 'ぶどう']

うまくできましたね。
ここまで見てきた通り、bit全探索は与えられた数に対してそれぞれ「選ぶ」「選ばない」を網羅して調べるときに使えます。
ただし、Nがあまりにも大きいと、パターンの数が膨大になってしまうため、bit全探索は使えません。

以上です。