115 關務特考四等 資訊處理(選試英文) 程式設計概要 考古題詳解
第 一 題30 分
請追蹤下列根基於 C++ 所撰寫的程式,列出輸出結果。每項輸出皆要說明為何會輸出所對映數值的原因,以及受到哪些規則或副程式所決定的結果。
#include <iostream> int a = 10;
void testA(int a) { cout << "1. a = " << a << endl; a++; cout << "2. a = " << a << endl; }
void testB(void) { cout << "3. a = " << a << endl; a++; cout << "4. a = " << a << endl; }
void testC(int &a) { cout << "5. a = " << a << endl; a++; cout << "6. a = " << a << endl; }
int main() { int a = 100; cout << "7. a = " << a << endl; a++; testC(a); cout << "8. a = " << a << endl; a++; testB(); cout << "9. a = " << a << endl; a++; testA(a); cout << "10. a = " << a << endl; return 0; }
登入後即可作答並保存紀錄。
核心觀念
本題考查 區域變數與全域變數的作用範圍,以及 C++ 函式參數的 傳值呼叫與參照呼叫。
- 全域變數
int a = 10;:在函式外宣告,未被同名區域變數遮蔽時,函式可存取它。 - 區域變數
int a = 100;:在main函式內宣告,只在main的作用範圍內有效;在main中使用a時,指的是這個區域變數。 void testA(int a):參數a是區域副本,函式內遞增不會改變呼叫端的變數。void testC(int &a):參數a是參照,會直接指向呼叫端傳入的變數;函式內遞增會改變該變數。testB沒有同名區域變數或參數,因此使用的是全域變數a。
解題方法
依程式執行順序追蹤各變數,並在每次呼叫函式時確認函式內的 a 指向哪個變數。
main的區域變數初值為100,因此第 7 行輸出100;接著a++後變成101。- 呼叫
testC(a)時,參數是參照,直接對應main的區域變數a。函式先輸出101,遞增後變成102,再輸出102。返回main後,第 8 行仍輸出102。 main再執行a++,區域變數變成103。呼叫testB時,函式使用全域變數a,其值仍為10。函式輸出10,遞增後全域變數變成11,再輸出11。返回main後,區域變數仍為103,所以第 9 行輸出103。main再執行a++,區域變數變成104。呼叫testA(a)時,傳入的是值的副本;函式內參數初值為104,遞增後變成105,但不會改變main的區域變數。
第 二 題20 分
給定二個方形,方形 A 的左上角座標 ,寬和高為 ;方形 B 的左上角座標 ,寬和高為 ,請設計判斷邏輯,以確認二個方形是否有任何重疊。有重疊回傳 true,否則回傳 false。
🖼️【此處有附圖,請對照原卷】
登入後即可作答並保存紀錄。
核心觀念
本題考察「軸對齊矩形」的重疊判斷。雖然題目稱為方形,但已分別給定寬度 與高度 ,因此以矩形處理。
由左上角座標與寬、高,可得到:
- 方形 A 的右邊界:
- 方形 A 的下邊界:
- 方形 B 的右邊界:
- 方形 B 的下邊界:
依圖示採用螢幕座標系統, 座標向下增加。
解題方法
兩個方形有重疊,必須同時滿足:
- 水平方向有共同區間
- 垂直方向有共同區間
水平方向的重疊長度為:
垂直方向的重疊長度為:
若兩個重疊長度都大於 ,代表具有實際面積的重疊,因此判斷式為:
且
程式設計
第 三 題25 分
以圖示法表示下列遞迴程式呼叫執行的過程,給定 、 來呼叫(即 )副程式,來求解最後回傳的結果。請依產生的堆疊並以分支圖示呈現此呼叫之過程。
R = {}
def pascal(n, k): if k == 0 or k == n: return 1 if (n, k) in R: return R[(n, k)] R[(n, k)] = pascal(n-1, k-1) + pascal(n-1, k) return R[(n, k)]
登入後即可作答並保存紀錄。
核心觀念
本題考遞迴的呼叫與回傳順序,以及記憶化(memoization):將已計算的 結果存入字典 ,後續遇到相同參數時直接取用,避免重複計算。
程式的邊界條件是 或 時回傳 ;其餘情況依帕斯卡公式計算:
本題不涉及法條,也不是選擇題,無須分析選項。
解題方法
從 pascal(4,2) 展開呼叫。每個非邊界呼叫先計算左分支 pascal(n-1, k-1),再計算右分支 pascal(n-1, k);子呼叫完成後才回傳並相加。遇到邊界條件直接回傳 ,遇到已在 中的參數則直接取用。
pascal(4,2)
├─ pascal(3,1)
│ ├─ pascal(2,0) → 1
│ └─ pascal(2,1)
│ ├─ pascal(1,0) → 1
│ └─ pascal(1,1) → 1
│ 回傳 1 + 1 = 2;R[(2,1)] = 2
│ 回傳 1 + 2 = 3;R[(3,1)] = 3
└─ pascal(3,2)
├─ pascal(2,1) → 查詢 R,取用 2
└─ pascal(2,2) → 1
回傳 2 + 1 = 3;R[(3,2)] = 3
回傳 3 + 3 = 6;R[(4,2)] = 6
呼叫堆疊的深度優先執行順序如下。每個子呼叫完成回傳後,才會執行同一層的下一個分支:
第 四 題25 分
二位富翁張三和李四比較誰較有錢。為保有隱私,互不直接說出財富金額,依此設定一個零知識證明程式,給定二維陣列分別標記二位富翁所擁有的財富。
假設一個陣列序號代表所擁有資產的一個單位(如:1 千萬),下表所示張三擁有 4 千萬,則分別標記 1 到 4 為 ;李四擁有 6 千萬,則分別標記 1 到 6 為 。
依此,於檢視誰比較有錢時,張三只能檢視李四第 4 個陣列格,李四只能檢視張三第 6 個陣列格。若有檢視到標記 ,則可以確認對方擁有的財富等同自己或在自己之上,反之則反。
| 財富擁有者 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | … |
|---|---|---|---|---|---|---|---|---|
| 張三 | - | - | - | … | ||||
| 李四 | - | … |
請設計一虛擬碼程式,以分別讓二位富翁運用此程式,來驗證是否比對方有錢。
登入後即可作答並保存紀錄。
核心觀念
本題考查:
- 二維陣列的索引存取。
- 以自己的財富數量作為索引,檢視對方陣列對應位置。
- 零知識證明的基本概念:不直接公開財富數字,只公開比較結果。
若某人的財富為 ,則其陣列滿足:
因此,檢視對方的第 格:
- 若為 ,表示對方財富至少為 ,即對方財富 自己。
- 若為 ,表示對方財富少於 ,即對方財富 自己。
解題方法
設:
Zhang:張三的財富陣列。Li:李四的財富陣列。wZhang:張三自己的財富數量。wLi:李四自己的財富數量。
每位富翁只能使用自己的財富數量作為索引,查詢對方陣列中的一格。
虛擬碼
function Verify(myWealth, opponentArray):
result ← opponentArray[myWealth]
if result == T:
return "對方財富等於或多於自己"
else:
return "對方財富少於自己"
張三執行:
function ZhangVerify(wZhang, Li):
return Verify(wZhang, Li)
李四執行:
function LiVerify(wLi, Zhang):
return Verify(wLi, Zhang)
完整流程如下:
ZhangResult ← ZhangVerify(wZhang, Li)
LiResult ← LiVerify(wLi, Zhang)
輸出 ZhangResult
輸出 LiResult
以題目數值說明
題目中:
- 張三擁有 千萬,因此
wZhang = 4。 - 李四擁有 千萬,因此
wLi = 6。
張三檢視李四的第 格:
因此張三得知:
也就是李四的財富等於或多於張三。
李四檢視張三的第 格:
因此李四得知: