生成子集
阿新 • • 發佈:2018-11-14
增量構造法
// {0~n-1}的所有子集:增量構造法
// Rujia Liu
#include<cstdio>
using namespace std;
void print_subset(int n, int* A, int cur) {
for(int i = 0; i < cur; i++) printf("%d ", A[i]); // 列印當前集合
printf("\n");
int s = cur ? A[cur-1]+1 : 0; // 確定當前元素的最小可能值
// 定序
for(int i = s; i < n; i++) {
// 一次選出一個元素放到集合中
// 如果無法繼續新增元素,自然就不會再遞迴了
A[cur] = i;
print_subset(n, A, cur+1); // 遞迴構造子集
}
}
int A[10];
int main() {
int n;
scanf("%d", &n);
print_subset(n, A, 0);
return 0;
}
輸入輸出
位向量法
構造一個位向量B[i],而不是直接構造子集A本身,其中B[i]=1,當且僅當i在子集A中。
必須當“所有元素是否選擇”全部確定完畢後才是一個完整的子集,因此仍然像以前那樣當if(cur == n)
成立時才輸出。
// {0~n-1}的所有子集:位向量法
// Rujia Liu
#include<cstdio>
using namespace std;
void print_subset(int n, int* B, int cur) {
if(cur == n) {
for(int i = 0; i < cur; i++)
if(B[i]) printf("%d ", i); // 列印當前集合
printf("\n");
return;
}
B[cur] = 1; // 選第cur個元素
print_subset(n, B, cur+1);
B[cur] = 0; // 不選第cur個元素
print_subset(n, B, cur+1);
}
int B[10];
int main() {
int n;
scanf("%d", &n);
print_subset(5, B, 0);
return 0;
}
輸入輸出
二進位制法
用二進位制來表示{0, 1, 2,…,n-1}的子集S:從右往左第i位(各位從0開始編號)表示元素i是否在集合S中。
// {0~n-1}的所有子集:二進位制法
// Rujia Liu
#include<cstdio>
using namespace std;
// 列印{0, 1, 2, ..., n-1}的子集S
void print_subset(int n, int s) {
for(int i = 0; i < n; i++)
// 這裡利用了C語言“非0值都為真”的規定
if(s&(1<<i)) printf("%d ", i);
printf("\n");
}
int main() {
int n;
scanf("%d", &n);
// 列舉各子集所對應的編碼 0, 1, 2, ..., 2^n-1
for(int i = 0; i < (1<<n); i++)
print_subset(n, i);
return 0;
}