藍橋杯備賽-列舉問題總結
遞迴實現指數型列舉
【問題描述】
從 \(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