開啟章節選單
位元枚舉
罕見簡介
位元枚舉是一種枚舉的技巧,通常用來枚舉所有的子集合。在這個技巧中,我們將集合中的元素用二進位表示,然後對二進位進行枚舉。
例如,對於集合 ,我們可以用 個位元來表示,其中第 個位元為 表示元素 在子集合中,為 表示元素 不在子集合中。這樣,我們就可以用 , , , , , , , 來表示所有的子集合。
實作方式
首先我們需要一個 變數,用來儲存目前的子集合,雖然 是一個整數,但我們可以將其視為一個二進位數字來操作。
如果要枚舉 到 ,實際上整數就是 到 ,也就是 到 。因此,我們可以用以下的迴圈來枚舉所有的子集合。
for (int mask = 0; mask < (1 << n); mask++) { }
接著,我們可以用以下的方法來判斷第 個元素是否在子集合中。
if (mask & (1 << i)) { // 第 i 個元素在子集合中 }
整個程式碼如下:
for (int mask = 0; mask < (1 << n); mask++) { for (int i = 0; i < n; i++) { if (mask & (1 << i)) { // 第 i 個元素在子集合中 } else { // 第 i 個元素不在子集合中 } } }
這樣,我們就可以用位元枚舉的方式來枚舉所有的子集合了!
例題
給定一個長度為 的數列,從中選出一些數字,使得這些數字的和儘可能接近且不超過 ,請你輸出最接近且不超過 的和。
根據上面介紹的方法,我們可以用以下的程式碼來解決這個問題。
for (int mask = 0; mask < (1 << n); mask++) { int sum = 0; for (int i = 0; i < n; i++) { if (mask & (1 << i)) { sum += a[i]; } } if (sum <= k) { ans = max(ans, sum); } }