c + + subset enumeration

Posted by drkstr on Mon, 21 Feb 2022 06:17:47 +0100

I believe everyone has done it Roast Chicken This problem. but 10 10 10 cycles is too much trouble. To 100 , 1000 100,1000 100, 1000 cycles?

Subset enumeration!

1, Definition of subset enumeration

What is subset enumeration?

  • For one data, if each data has only 2 2 Two states, for example: select or not, select the first or the second... At this time, subset enumeration becomes a good choice.
  • Because each data has only 2 2 Two states, from which we can think of 2 2 Binary. 0 0 0 represents the first state, 1 1 1 represents the second state. At this time, the representation of each decimal number in binary represents a state.

2, Code implementation

#include <cstdio>
#include <algorithm>
using namespace std;

int n;  // n means there are several data in total

// Subset enumeration
void work() {
    int U = (1 << n); // (1 < < n) means pow(2, n). But the difference is that (1 < < n) is of type int and pow(2, n) is of type double. Choose according to the situation.
    // 0 (10) = 0000 (2) is an option, but u (10) = 100 0 (n zeros) is not a selection. So the enumeration range is [0, U).
    for(int S = 0; S < U; S++) /*Traverse each case*/ {
        if(/*Judgment statement*/ )
            /*Execute statement*/;
    }
    /*
    Example:
    int ans = 0;
    for(int S = 0; S < U; S++) {
        if(__builtin_popcount(S) == k) // This function means to calculate the number of S in binary.
            ans++;
    }
    printf("%d", ans);
    */
    printf(/*Output content*/);
    return ;    // return.
}

int main() {
    scanf("%d", &n);
    work();
    return 0;
}

3, Examples

P1657 selected books

time limit

1.00s

Memory limit

125.00MB

Title Description

During the school winter vacation, the tutor of the Olympic Games of Informatics has 1, 2, 3... X books, which should be distributed to x people participating in the training. Each person can only choose one book, but each person has two favorite books. The teacher asked everyone to fill in a form with their favorite books in advance. Then distribute the books according to the form they fill in, hoping to design a program to help the teacher find out all possible distribution schemes and make every student satisfied.

Input format

Line 1: a number x

Line 2 ~ line 1+x: two numbers in each line, indicating the serial number of the book ai likes

Output format

There is only one number: total number of schemes.

Sample input and output

Enter #1 copy
5
1 3
4 5
2 5
1 4
3 5

Output #1 copy

2

Description / tips

All data: x < = 20

(there is not one of the most difficult data topics in the world...)

analysis

(it was originally daoshen search, but I wrote it as subset enumeration)
First, analyze the topic. Each student has only two favorite books, which can be regarded as two situations.
See code Notes for ideas:

#include <cstdio>
#include <iostream>
#include <memory.h>
using namespace std;

int n, U;
int book[25][3];
int judge[25];

// input
void input() {
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < 2; j++)
            scanf("%d", &book[i][j]), book[i][j]--;
    U = 1 << n;
    // printf("%d", U);

    return ;
}

/*
Subset enumeration idea:
    Each person chooses two books a1, a2. Select a1 as 0 and a2 as 1. Define variable U, then U-1 is the complete set and the range is 
[0, U) . Operation (U & (1 < < i)) is to judge whether the ith student chose the first book or the second book. The value of 0 is the first book, and the value is not 
0 It's the second book.
*/

// Subset enumeration
void work(int U) {
    int ans = 0;
    int f = 1;
    for(int S = 0; S < U; S++) {
        f = 1;
        memset(judge, 0, sizeof(judge));
        for(int i = 0; i < n; i++)
            if(S & (1 << i))
                judge[book[i][1]]++;
            else 
                judge[book[i][0]]++;
        for(int i = 0; i < n; i++)
            if(judge[i] != 1) {
                f = 0;
                break;
            }
        //     printf("%d: ", S);
        // for(int i = 0; i < n; i++)
        //     printf("%d ", judge[i]);
        // puts("");
        if(f) {
            ans++;
            // printf("%d\n", S);
        }
            
    }

    printf("%d\n", ans);
}

int main() {
    input();
    if(n == 0) {
        printf("0");
        return 0;
    }
    work(U);

    return 0;
}

4, Complexity analysis

The time complexity of subset enumeration is O ( 2 n ) O(2^n) O(2n), so there is nothing to do about the problem of too large data. general requirements n ≤ 20 n \le 20 n≤20.

Topics: C++