n 개 중 m 개 고르는 조합 (all possible combinations)
n 개 가운데 m 개를 고르는 모든 조합
void pick(int n, vector<int> &picked, int remain) {
if (remain == 0) {
//do_something_with(picked);
return;
}
int mini = picked.empty() ? 0 : picked.back() + 1;
for (int i = mini; i < n; i++) {
picked.push_back(i);
pick(n, picked, remain - 1);
picked.pop_back();
}
}
uint32 next(uint32 v) {
uint32 w;
uint32 t = v | (v - 1);
w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
return w;
}
// n <= 31
void pick(int n, int m) {
uint32 i = (1 << m) - 1;
uint32 maxi = (1 << n) - 1;
while (maxi >= i) {
//do_something_with(i);
i = next(i);
}
}
첫 번째 방법은 vector 를 이용하여 적절한 index 를 push 하는 방법이다. 일반적인 방법.
두 번째는 n 이 31 이하인 경우 사용가능하다. bit 연산을 하므로 매우 빠르다. 대략 비교해 보면 후자가 5 ~ 7 배 빠른 것같다. (물론 경우에 따라 다르겠지만)
어차피 n 이 너무 커지면 경우의 수가 너무 많아 계산이 불가능하므로, 후자가 유용하게 사용될 수 있을 듯.
구글링 해 보니 요런 것도 있다. http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/
Written on June 19, 2014