ビット全探索で部分集合を列挙
選ぶ・選ばないの N 個の判断を、N 桁の2進数に対応させます。全体で 2^N 通りです。
言語:Python / 計算量:O(N 2^N)
考え方
- mask の i 桁目が1なら i 番目を選びます。
- mask >> i & 1 でその桁を調べます。
- 空集合も1つの候補です。
具体例
3要素なら mask=5 は2進数で101。0番目と2番目を選びます。
実装
a = [2, 3, 5]
for mask in range(1 << len(a)):
total = 0
for i, x in enumerate(a):
if mask >> i & 1:
total += x
print(mask, total)注意する条件
N=40 なら約1兆通り。半分全列挙やDPへ切り替える規模です。
確認問題
4要素の部分集合は空集合込みで何通り?
解答と理由
16
それぞれ2択なので2^4=16です。
実装課題
N K と配列 A。和がKとなる部分集合の個数を求める。0 ≤ N ≤ 18、0 ≤ A_i,K ≤ 10^6。添字で区別。空集合も含む。
入力:
3 5
2 3 5
出力:
2参考実装
n, k = map(int,input().split())
a = list(map(int,input().split()))
ans = 0
for mask in range(1 << n):
s = 0
for i in range(n):
if mask >> i & 1:
s += a[i]
ans += s == k
print(ans)