ACM 利用位運算列舉所有子集
阿新 • • 發佈:2019-02-05
給集合裡的元素一個順序,那麼就可以用整數表示集合,某一位為1表示對應元素被選取。
設x為表示集合的整數,那麼這個整數有如下性質:
x的子集整數y在數值上不會比x大。因為x的子集y只是保留了x某些位置上的1,所以y總可以加上一個非負的整數z等於x,相當於把沒選的1補上。
根據這個性質可知,可以通過列舉所有比x小的數p並判斷,p是否只含x對應位上的1,如果是則p是x的子集,否則不是。這樣時間複雜度是嚴格的x。有沒有更快的呢,有的。
上訴列舉p是通過減一操作,並且我們知道減一操作一定是正確的,那麼在列舉的時候如何快速的去掉多餘的狀態,答案就是和x進行&(與)運算。與運算可以快速跳到下一個子
集。
&運算本質就是保留p在x對應位為1的數值,而根據二進位制減法可知減一操作都是把p最低位的1消去,在那一位後全補上1,如果在x對應位為0的地方產生了1其實是無效的,
後續的減一操作也會把它消掉,所以直接&運算可以快速去掉多餘的狀態。時間複雜度是x的子集數。
程式碼如下:
for(int i=x;i;){
i=(i-1)&x;
}