生成子集 (增量构造法)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成子集 (增量构造法)相关的知识,希望对你有一定的参考价值。

使用增量构造法可以构造出升序数组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;
}
View Code

如果要构造如下这样的排序的话,以输入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;
}
View Code

 







以上是关于生成子集 (增量构造法)的主要内容,如果未能解决你的问题,请参考以下文章

子集生成——增量构造法+位向量法+二进制法

子集生成——增量构造法

算法竞赛入门经典7.3子集生成增量构造法位向量法二进制法

『模板』 子集生成

子集生成

子集生成