Submask Enumeration¶
Enumerating all submasks of a given mask¶
Given a bitmask
Consider the implementation of this algorithm, based on tricks with bit operations:
int s = m;
while (s > 0) {
... you can use s ...
s = (s-1) & m;
}
or, using a more compact for
statement:
for (int s=m; s; s=(s-1)&m)
... you can use s ...
In both variants of the code, the submask equal to zero will not be processed. We can either process it outside the loop, or use a less elegant design, for example:
for (int s=m; ; s=(s-1)&m) {
... you can use s ...
if (s==0) break;
}
Let us examine why the above code visits all submasks of
Suppose we have a current bitmask (s-1) & m
. As a result, we "cut" mask
Thus, this algorithm generates all submasks of this mask in descending order, performing only two operations per iteration.
A special case is when (s-1) & m
we will have that
Iterating through all masks with their submasks. Complexity ¶
In many problems, especially those that use bitmask dynamic programming, you want to iterate through all bitmasks and for each mask, iterate through all of its submasks:
for (int m=0; m<(1<<n); ++m)
for (int s=m; s; s=(s-1)&m)
... s and m ...
Let's prove that the inner loop will execute a total of
First proof: Consider the
- it is not included in the mask
- it is included in
- it is included in both
As there are a total of
Second proof: Note that if mask
To calculate this number, note that the sum above is equal to the expansion of