1. 程式人生 > 其它 >藍橋杯備賽-列舉問題總結

藍橋杯備賽-列舉問題總結

遞迴實現指數型列舉

【問題描述】

\(1 \sim n\)\(n\) 個整數中隨機選取任意多個,輸出所有可能的選擇方案。

【輸入格式】

輸入一個整數 \(n\)

【輸出格式】

每行輸出一種方案。

同一行內的數必須升序排列,相鄰兩個數用恰好 11 個空格隔開。

對於沒有選任何數的方案,輸出空行。

【輸入樣例】

3

【輸出樣例】

3
2
2 3
1
1 3
1 2
1 2 3

【分析】

如例題所示,1-3之間的數一共有8種選擇方案,即\(2^3\)就是三個數選或者不選這兩種,可以採用遞迴的方法來實現

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

int st[30];
int p[30], n;

void dfs(int u) {
    if (u == n) {  // 注意這裡應該試u == n,不能是u > n.
        for (int i = 0; i < n; i ++) {
            if (st[i] == 1) cout << i + 1 << ' ';
        }
        cout << endl;
        return;
    }
    
    st[u] = 1;  // 選u+1
    dfs(u + 1);
    st[u] = 0;
    
    st[u] = 2;  // 不選u+1
    dfs(u + 1);
    st[u] = 0;
}

int main()
{
    cin >> n;
    dfs(0);
    
    return 0;
}

【拓展】用二進位制進行列舉,程式碼更短更好理解

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

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < (1 << n); i ++) {
        for (int j = 0; j < n; j ++) {
            if (i & (1 << j)) {
                cout << j + 1 << ' ';
            }
        }
        cout << endl;
    }
    
    return 0;
}

遞迴實現排列型列舉(全排列\(A^n_n\)

【問題描述】

\(1 \sim n\)\(n\) 個整數排成一行後隨機打亂順序,輸出所有可能的次序。

【輸入格式】

輸入一個整數 \(n\)

【輸出格式】

按照從小到大的順序輸出所有方案,每行 \(1\) 個。

首先,同一行相鄰兩個數用一個空格隔開。

其次,對於兩個不同的行,對應下標的數一一比較,字典序較小的排在前面。

【輸入樣例】

3

【輸出樣例】

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

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

int n;
bool st[20];
int p[20];

void dfs(int u) {
    if (u == n) {
        for (int i = 0; i < n; i ++) cout << p[i] << ' ';
        cout << endl;
        return;
    }
    
    for (int i = 1; i <= n; i ++) {
        if (!st[i]) {
            st[i] = true;
            p[u] = i;
            dfs(u + 1);
            p[u] = 0;
            st[i] = false;
        }
    }
}

int main()
{
    cin >> n;
    dfs(0);
    
    return 0;
}

遞迴實現組合型列舉

【問題描述】

\(1 \sim n\)\(n\) 個整數中隨機選出 \(m\) 個,輸出所有可能的選擇方案

【輸入格式】

輸入 \(n, m\)

【輸出格式】

按照從小到大的順序輸出所有方案,每行 1 個。

首先,同一行內的數升序排列,相鄰兩個數用一個空格隔開。

其次,對於兩個不同的行,對應下標的數一一比較,字典序較小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

【輸入樣例】

3

【輸出樣例】

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

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

const int N = 50;
int n, m;
int p[N];
bool st[N];

void dfs(int u, int s) {
    if (u == m) {
        for (int i = 0; i < m; i ++) cout << p[i] << ' ';
        cout << endl;
    }
    
    for (int i = s; i <= n; i ++) {
        if (!st[i]) {
            st[i] = true;
            p[u] = i;
            dfs(u + 1, i + 1);
            p[u] = 0;
            st[i] = false;
        }
    }
}

int main()
{
    cin >> n >> m;
    dfs(0, 1);
    
    
    return 0;
}

C++中全排列函式\(next \_ permutation\)用法

​ 運用next_permutation函式計算全排列以遞迴實現排列型列舉為例,對函式進行介紹。next_permutation函式的作用產生當前數列的下一個全排列例如:

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

int main()
{
    int num[3] = {1, 2, 3};
    do {
        for (int i = 0; i < 3; i ++) {
            cout << num[i] << ' ';
        }
        cout << endl;
    } while (next_permutation(num, num + 3));

    return 0;
}

【輸出結果】

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1