【備忘録】bit全探索

python3
あくまで備忘録なんで雑に記録します

①bit全探索の使い方

2^nの全探索(重複順列)を処理したかったのですが、やり方がわからず調べて「bit全探索」に辿り着きました。自分の勉強のため、引用元の方と同じ様な記事になります。
※ただし、O(2^n)なことには注意!

n = 2〜3位なら for を積み重ねるのも良いけど、n自体が変数なら無理
2^100 → 31桁(1267650600228229401496703205376)

問題

引用

(引用)

問題文
みかん(100円)りんご(200円)ぶどう(300円)がそれぞれ1つずつ果物屋さんにありました。財布の中には300円ありますが、考え得るすべての買い物パターンを列挙しなさい。

Python de アルゴリズム(bit全探索)より引用

2^3の8通りで
なし:0円❌
みかん:100円⭕️
りんご:200円⭕️
ぶどう:300円⭕️
みかん・りんご:300円⭕️
みかん・ぶどう:400円❌
りんご・ぶどう:500円❌
みかん・りんご・ぶどう:600円❌

n種類の果物として、10進数No.は「2^n」
bit表示の左から右までの幅が「n」

ここまでは簡単に思いつけるかもしれなかったけど、各判定に

『bit表示を1の位までシフトして、001と&(論理積)をとる』というのは目から鱗
例えば
パターン3のみかんは、2ビット右へシフトして&1でFalse
パターン2のりんごは、1ビット右へシフトして&1でTrue10

mikan = 100
ringo = 200
budou = 300
A = [mikan, ringo, budou]
B = ['みかん', 'りんご', 'ぶどう']

count = 0

for i in range(2**3): #10進数No.でまわしていく
    nedan = 0
    bag = []
    for j in range(3): #iは右から、ぶどうが0、りんごが1、みかんが2
        if (i >> j) & 1 == True: #==Trueはなくてもけれど敢えて
            nedan += A[-(j+1)] #右からj+1番目だから
            bag.append(B[-(j+1)]) #バッグにもいれていく
    if nedan != 0 and nedan <= 300: #0円も省いて300円以下をカウント
        count += 1
        print(bag,nedan) #都度プリント

print('全部で', count, 'パターン')

コメント

タイトルとURLをコピーしました