算是徹底搞懂二進制枚舉吧。
首先一個集合的子集有2^n個,所以我們枚舉的個數有(1<<n)個;
所以
for(int i=0; i<(1<<n); i++)
我們知道二進制枚舉的過程如下:
每個位置值為1則保留,不為1則舍棄 ;
設s=13(二進制為1101)那么我們保留0 2 3位置上的數值;
那么我們如何找到每個位置上的數值呢?
我們遍歷的是二進制的十進制表示(比如13),我們當然可以轉化為二進制在枚舉每一位,但是,這很麻煩;
一個很巧妙的方式就是利用位運算;
1<<0=1(0);
1<<1=2(10);
1<<2=4(100);
1<<3=8(1000);
1<<4=16(10000);
...
1<<7=128(10000000);
...
看出來了吧!我們只需要將13&(1<<i)我們便可以得到每一位是不是1 (1<<i除了那一位,剩余的都是0,所以我么就可以得到那一位是不是1)
因此,我們便有了:
for(int i=0; i<n; i++) if(s&(1<<i)) printf(" %d ",a[i]);
完整代碼:
for(int i=0; i<(1<<n); i++) { for(int i=0; i<n; i++) { if(s&(1<<i)) printf(" %d ",a[i]); } }
這只是將子集輸出,你也可以將枚舉出的子集存到數組或容器(vector等)里,以便他用;