使用增量构造法可以构造出升序数组arr的不重复子集,并且按字典序排序
#include<bits/stdc++.h> using namespace std; int arr[16]; inline void print_subset(int *index, int cur, int n)///cur值这里可以理解为在这个堆栈层子集的集合数 { for(int i=0; i<cur; i++) {printf("%d ", arr[index[i]]);} if(cur)puts(""); int s = cur ? index[cur-1]+1 : 0;///因为index是arr升序序列的下标,这里cur就是当前arr可能最小值的下标 for(int i=s; i<n; i++){ index[cur] = i; print_subset(index, cur+1, n); } } int main(void) { int n, index[16];///index数组辅助构造,其值为升序序列的下标,注意是从0开始 for(int i=0; i<16; i++) index[i] = i; while(~scanf("%d", &n)){ int cur = 0; for(int i=0; i<n; i++) arr[i] = i+1;///这里arr的值为1~n的一个序列 print_subset(index, cur, n); puts(""); } return 0; }
如果要构造如下这样的排序的话,以输入3为例
1
2
3
1 2
1 3
2 3
1 2 3
可以在原有的基础上使用一个结构体将每个子集的长度和具体序列用int和string存起来就能通过二级排序构造出来了
#include<bits/stdc++.h> using namespace std; int arr[16]; struct item { int len, digit[16]; string s; }; bool cmp(const item fir, const item sec) { if(fir.len==sec.len) return fir.s < sec.s; return fir.len < sec.len; } item ans[1<<16]; int top = 0; inline void print_subset(int *index, int cur, int n) { //for(int i=0; i<cur; i++) {printf("%d ", cur);printf("%d ", arr[index[i]]);} puts(""); ans[top].len = cur; stringstream temp; for(int i=0; i<cur; i++){ ans[top].digit[i] = arr[index[i]]; } temp<<ans[top].digit; temp>>ans[top].s; top++; temp.clear(); int s = cur ? index[cur-1]+1 : 0; for(int i=s; i<n; i++){ index[cur] = i; print_subset(index, cur+1, n); } } int main(void) { int n, index[16]; for(int i=0; i<16; i++) index[i] = i; while(~scanf("%d", &n)){ int cur = 0; top = 0; for(int i=0; i<n; i++) arr[i] = i+1; print_subset(index, cur, n); sort(ans, ans+top, cmp); for(int i=0; i<top; i++){ // if(ans[i].len) printf("%d ", ans[i].len); for(int j=0; j<ans[i].len-1; j++){ printf("%d ", ans[i].digit[j]); } printf("%d", ans[i].digit[ans[i].len-1]); puts(""); } puts(""); } return 0; }
时间: 2024-10-21 10:06:35