@@ -118,7 +118,7 @@ int main()
118118
119119## 解題說明
120120
121- 本題要求實現輸出集合 $S$ 的所有子集合,假設 $S = '{' a, b, c'}' $ 。
121+ 本題要求實現輸出集合 $S$ 的所有子集合,假設 $S = {{ a, b, c}} $ 。
122122
123123### 解題策略
124124
@@ -128,8 +128,8 @@ int main()
128128
129129### 解題範例
130130
131- 假設集合 $S = {a, b, c}$,其所有子集合為:
132- $ {}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}$
131+ 假設集合 $S = {a, b, c}$,其所有子集合為:
132+ ``` {}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}```
133133共 $2^3 = 8$ 種子集合。
134134
135135## 程式實作
@@ -138,26 +138,27 @@ ${}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}$
138138
139139```cpp
140140#include <iostream>
141+ #include <cmath>
141142using namespace std;
142- int A(int m, int n)
143- {
144- if (m == 0)
145- return n + 1;
146- else if (n == 0)
147- return A(m - 1, 1);
148- else
149- return A(m - 1, A(m, n - 1));
150- }
151143
152- int main()
153- {
154- int m, n, a;
155- cout << "請輸入m:";
156- cin >> m;
157- cout << "請輸入n:";
158- cin >> n;
159- a = A(m, n);
160- cout << "A = " << a;
144+ int main() {
145+ char S[] = { 'a', 'b', 'c' };
146+ int n = 3;
147+ int total = pow(2, n);
148+
149+ for (int i = 0; i < total; ++i) {
150+ cout << "{";
151+ bool first = true;
152+ for (int j = 0; j < n; ++j) {
153+ if (i & (1 << j)) {
154+ if (!first) cout << ", ";
155+ cout << S[j];
156+ first = false;
157+ }
158+ }
159+ cout << "}" << endl;
160+ }
161+ return 0;
161162}
162163```
163164
@@ -170,14 +171,16 @@ int main()
170171
171172### 測試輸出
172173
173- ${}$
174- ${a}$
175- ${b}$
176- ${a, b}$
177- ${c}$
178- ${a, c}$
179- ${b, c}$
180- ${a, b, c}$
174+ ```
175+ {}
176+ {a}
177+ {b}
178+ {a, b}
179+ {c}
180+ {a, c}
181+ {b, c}
182+ {a, b, c}
183+ ```
181184
182185### 結論
183186
@@ -191,12 +194,12 @@ ${a, b, c}$
191194
192195在本程式中,使用遞迴來實現阿克曼函數的主要原因如下:
193196
194- 1 . ** 程式邏輯簡單直觀**
195- Ackermann 函數的遞迴寫法明確表達了「將問題拆解為更小的子問題」的核心概念。
196- 根據其數學定義,每一次呼叫 $A(m, n)$ 都會轉化為更簡單的子問題,直到遇到邊界條件 $m$ 為 $0$ 為止。
197+ 1 . ** 結構簡單、貼近子集的定義**
198+ 遞迴自然符合「選擇與不選擇」的兩分策略,程式碼易於理解與實作。
197199
198- 2 . ** 遞迴語意清楚、結構分明 **
199- 每一次 $A(m, n)$ 的遞迴呼叫都代表著一個「子問題的解」,且其回傳值會逐層傳遞回原本的呼叫點,組合成最終結果 。
200- 這種設計讓程式結構簡潔,能夠清楚地追蹤問題的拆解與合併過程。
200+ 2 . ** 適合列舉所有組合情形 **
201+ 遞迴結構可完整走訪所有可能的子集合,不會遺漏也不重複 。
202+
201203
202- 本程式缺點主要表現在遞迴深度限制,當函數遞迴層數過深時,每一層的呼叫都會佔用一部分的記憶體(堆疊空間)。如果超出所允許的堆疊大小限制,就會發生Stack Overflow,導致程式中斷運行或崩潰。
204+ 效能瓶頸:
205+ 若集合元素超過 20 個,子集合數量達 $2^{20} = 1048576$,執行效率將明顯下降。
0 commit comments