[Aizu] ITP2_11_A~D: 子集的枚举系列

Posted by-sknight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Aizu] ITP2_11_A~D: 子集的枚举系列相关的知识,希望对你有一定的参考价值。

前言

ITP系列之使用位集枚举, 具体内容参见bitset
PS: 感觉第三个与第四个拓展之后实用性较强

题目链接

ITP2_11_A: Enumeration of Subsets I
ITP2_11_B: Enumeration of Subsets II
ITP2_11_C: Enumeration of Subsets III
ITP2_11_D: Enumeration of Combinations

求解

第一题

分析

要求n个数的组合, 组合内元素数量不限, 创建一个位集, 从0一直增加到小于2的n次方即可, 每次都输出

代码

#include <bits/stdc++.h>
using namespace std;
 
void print(bitset<20> b) 
    for (int i = 0; i < 20; i++) 
        if (b.test(i)) 
            cout << " " << i;
        
    

 
int main(void) 
    ios::sync_with_stdio(false);
    cin.tie(0);
 
    bitset<20> b1, b2;
    int n;
 
    cin >> n;
    int max = 1 << n;
    for (int i = 0; i < max; i++) 
        cout << i << ":";
        b2 = i;
        print(b2);
        cout << endl;
    

第二题

分析

求n个数的组合, 组合满足T集合是它的子集, 如T = 1, 2, 那么形如1, 2, 3, 1, 2, 5等这种都可以, 2, 3, 5 这种不可以

代码

#include <bits/stdc++.h>
using namespace std;
 
void print(bitset<20> b) 
    for (int i = 0; i < 20; i++) 
        if (b.test(i)) 
            cout << " " << i;
        
    

 
int main(void) 
    ios::sync_with_stdio(false);
    cin.tie(0);
 
    bitset<20> b1, b2;
 
    int n; cin >> n;
    int max = 1 << n;
    int k; cin >> k;
    for (int i = 0; i < k; i++) 
        int x; cin >> x;
        b1.set(x);
    
    for (int i = 0; i < max; i++) 
        b2 = i;
        if ((b2 | b1) == b2) 
            cout << i << ":";
            print(b2);
            cout << endl;
        
    

第三题

分析

给定一个集合T, 是S集合的子集, S集合是一个简单的集合 0 ~ n-1, 而T集合则是其中特定的元素的集合, 要求输出所有集合T的元素的全组合
通过用一个位集一点点增加上去, 会发生超时.
如果把T看作一个数组, 那么就可以使用一个长度为T的长度的位集, 来依次增加, 得到的一个位集作为T中元素的下标, 然后输出即可

代码

#include <bits/stdc++.h>
using namespace std;
 
void print(bitset<32> b) 
    for (int i = 0; i < 32; i++) 
        if (b.test(i)) 
            cout << " " << i;
        
    

 
int main(void) 
    ios::sync_with_stdio(false);
    cin.tie(0);
 
    bitset<32> b1, b2;
    vector<int> vec;
 
    int n; cin >> n;
    int k; cin >> k;
    int max = 1 << k;
    for (int i = 0; i < k; i++) 
        int x; cin >> x;
        vec.push_back(x);
    
    for (int i = 0; i < max; i++) 
        b1 = i;
        b2.reset();
        for (int j = 0; j < vec.size(); j++) 
            if (b1.test(j) == 1) 
                b2.set(vec[j]);
            
        
        cout << b2.to_ulong() << ":";
        print(b2);
        cout << endl;
    

第四题

分析

要求的是从n个数中取出k个数的全组合, n个数分别为 0 ~ n-1, 创建一个位集, 然后从值从0一直增加, 如果1的数量恰好为k个, 输出即可

代码

#include <bits/stdc++.h>
using namespace std;

int main(void) 
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, k; cin >> n >> k;
    bitset<18> b;
    int max = 1 << n;
    for (int i = 0; i < max; i++) 
        b = i;
        if (b.count() == k) 
            cout << i << ":";
            for (int j = 0; j < n; j++) 
                if (b.test(j))
                    cout << " " << j;
            
            cout << endl;
        
    

以上是关于[Aizu] ITP2_11_A~D: 子集的枚举系列的主要内容,如果未能解决你的问题,请参考以下文章

Aizu ITP2_6_A(二分模板)

[Aizu] ITP2_8_A: Map: Search

[Aizu] ITP2_6_C: Lower Bound

搜索的应用--计算最优解:Aizu - ALDS1_4_D Allocation

Stack,( Aizu - ALDS1_3_A)

Exhaustive Serch ( Aizu - ALDS1_5_A )