排列组合与集合的实现

本文借鉴于《挑战程序设计竞赛》第二版P156到P157页的内容自己实现
1:枚举{0,1,~,n-1}所包含的所有子集的方法

#include <cstdio>
#include <iostream>
using namespace std;
int used[10000];
int main(){
    int n;
    cin >> n;
    for(int i=0;i< 1 << n;i++){
        memset(used,0,sizeof(used));
        for(int j=0;j<n;j++) used[j] = i>>j & 1;
        for(int j=0;j<n;j++) cout << used[j];
        cout << endl;
    }
    return 0;
}

输入n=6我们可以得到如下的结果

000000
100000
010000
110000
001000
101000
011000
111000
000100
100100
010100
110100
001100
101100
011100
111100
000010
100010
010010
110010
001010
101010
011010
111010
000110
100110
010110
110110
001110
101110
011110
111110
000001
100001
010001
110001
001001
101001
011001
111001
000101
100101
010101
110101
001101
101101
011101
111101
000011
100011
010011
110011
001011
101011
011011
111011
000111
100111
010111
110111
001111
101111
011111
111111

2:枚举{0,1,~,n-1}所包含的所有大小为k的子集的方法即组合的实现

#include <cstdio>
#include <iostream>
using namespace std;
int k=3;
int used[10000];
int main(){
    int n;
    cin >> n;
    int comb=(1<<k) -1;
    while(comb < 1 << n){
        //***********************************
        //这里针对comb进行处理
        memset(used,0,sizeof(used));
        for(int i=0;i<n;i++) used[i] = comb>>i & 1;
        for(int i=0;i<n;i++) cout << used[i];
        cout << endl;
        //***********************************
        int x = comb & -comb, y = comb + x;
        comb = ((comb & ~y) / x >> 1) | y;
    }
    return 0;
}

输入n=6我们可以得到如下的结果

111000
110100
101100
011100
110010
101010
011010
100110
010110
001110
110001
101001
011001
100101
010101
001101
100011
010011
001011
000111

我们之后可以通过对used数组的操作来实现组合的效果

3:对集合{0,1,~,n-1}所有元素的全排列

#include <cstdio>
#include <iostream>
using namespace std;
int main(){
    int n,a[100000];
    cin >> n;
    for(int i=0;i<n;i++) a[i]=i;
    do{
        for(int i=0;i<n;i++) cout << a[i];
        cout << endl;
    }while(next_permutation(a,a+n));
    return 0;
}

输入n=4后得到

0123
0132
0213
0231
0312
0321
1023
1032
1203
1230
1302
1320
2013
2031
2103
2130
2301
2310
3012
3021
3102
3120
3201
3210

4:枚举集合n(二进制表示)所包含的所有子集的方法

#include <cstdio>
#include <iostream>
using namespace std;
int cal(int n){
    int res=0;
    while(n>0){
        n/=10;
        res++;
    }
    return res;
}
int main(){
    int n,used[10000];;
    cin >> n;
    int len=cal(n);
    int x=n;
    do{
        //***********************************************
        //对子集的处理
        memset(used,0,sizeof(used));
        for(int i=0;i< (1 << len);i++) used[i] = x>>i & 1;
        for(int i=0;i< (1 << len);i++) cout << used[i];
        cout << endl;
        //***********************************************
        x=(x-1) & n;
    }while(x != n);//处理完0后,会有-1&sup = sup;
    return 0;
}

我们输入182即01101101可以得到它所有的子集有这样的规律即原来位上是0则所有的子集这里也全是0,原来位上是1则子集里这里不一定是1

这里写代码片01101101
00101101
01001101
00001101
01100101
00100101
01000101
00000101
01101001
00101001
01001001
00001001
01100001
00100001
01000001
00000001
01101100
00101100
01001100
00001100
01100100
00100100
01000100
00000100
01101000
00101000
01001000
00001000
01100000
00100000
01000000
00000000
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

门豪杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值