AP325 練習題解 (Ch01)
前言
最近在找題目練習時,突然想到之前連第一章都沒看完的 AP325 (講義下載),決定趁著寒假讀一下,順便做個筆記。由於例題在講義內都有滿詳細的說明,因此這裡紀錄的解法以習題為主。
Q-1-2. 合成函數(2)
這題跟 P-1-1 用一樣的方法做就好了。不過我是用 C++ 寫的,因此在 eval()
裡判斷第一個輸入是不是數字的方法不同:
int n;
if (cin >> n && cin) return n;
cin.clear();
首先嘗試進行 cin,若讀取數字失敗,則 failbit 會被設置,此時 if (cin)
會是 false,因此只有當正確讀取數字才會 return n。由於 failbit 被設置時 cin 無法正常運作,因此執行 cin.clear()
清除 failbit 才能正常執行之後的 cin。
Q-1-4. 支點切割
這題可以用前綴和 (left prefix sum) 與後綴和 (right prefix sum) 來解。
lps[i]
表示從 left
到 i
的乘積總和,rps[i]
同理。根據題目的公式,abs(rps[i] - lps[i])
就是該切點的 cost。
以範例測資為例:
index | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
delta | 0 | p1 | p1 + p2 | p1 + p2 + p3 | p1 + p2 + p3 + p4 |
lps[i] | 0 | p1 | 2p1 + p2 | 3p1 + 2p2 + p3 | 4p1 + 3p2 + 2p3 + p4 |
index | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
delta | p2 + p3 + p4 + p5 | p3 + p4 + p5 | p4 + p5 | p5 | 0 |
rps[i] | p2 + 2p3 + 3p4 + 4p5 | p3 + 2p4 + 3p5 | p4 + 2p5 | p5 | 0 |
然後再找出 cost 最小的 i 即為此區間的最佳切點。
Q-1-5. 二維黑白影像編碼
這題直接照著題目敘述做就好了,將字串從左到右遍歷,遇到 1 就將 res
加上 ,遇到 2 就進入 的遞迴。
P-1-7. 子集合乘積
這題的迴圈作法有用到 bitwise operator,<<
與 >>
分別代表左移與右移,超出範圍(例如 int 有 32 bits)的 bits 被捨棄,另一側補 0。
個數字(包含重複)的子集合個數是 (需要排除空集合),每個數字分為有跟沒有兩種情況,可以用 bit 的 1 與 0 表示。例如 表示子集合個數為 25,第 11001
種情況代表此集合包含第 1、2、5 三個數字。
最後用 &
來檢查每一位是否為 1,11001 & 01000
的結果為 01000
,非零表示包含第 2 個數字。
P-1-9. N-Queen 解的個數
講義中提到可以用 abs(p[i] - p[j]) == j - i
來判斷是否在對角線,此處以 4 * 4 的棋盤為例,每個數字代表第幾個皇后,- 表示空格:
- | - | 2 | - |
- | - | - | 3 |
0 | - | - | - |
- | 1 | - | - |
由於 2 號皇后在第 0 列,3 號皇后在第 1 列,此時 p[2] = 0, p[3] = 1
。套用上面的條件,可以發現兩個皇后確實在同一個對角線上,1 號與 3 號同理。
第二個遞迴解的 i = k - j + p[j]
與 i = p[j] - (k - j)
代表的意思我想了很久,其實就只是對角線的位置。以上面的棋盤為例,假設目前 k = 1, j = 0, p = [2, ?, ?, ?]
(其他皇后位置未定),此時 valid = [T, T, F, T]
(直線也是攻擊範圍),套用兩個算式得到 i
分別為 1, 3,頂式此兩格處於其他皇后的攻擊範圍,標記為不可放置,valid = [T, F, F, F]
。
Q-1-10. 最多得分的皇后
這題可以用 P-1-9 的遞迴解,需要考慮的部分是不一定要放滿 n 個皇后,我用 -1 表示不放,最後計算分數時遇到 -1 不算該格分數(但是這個方法不夠優化)。
下面是最關鍵的部分,迴圈裡面照一般的解法,結束後追加一個 -1 表示此列不放皇后,res
用於儲存最高的分數。
for (int i = 0; i < n; i++) {
if (valid[i]) {
p[k] = i;
res = max(res, nq(n, k + 1, p));
}
}
p[k] = -1;
res = max(res, nq(n, k + 1, p));
Q-1-11. 刪除矩形邊界 — 遞迴
這題可以把矩陣設為全域變數,這樣遞迴函式只需要傳入四個邊界與 cost。直接計算四個邊各自的 cost,再縮減邊界繼續遞迴即可。如果左邊界等於右邊界,或上邊界等於下邊界,表示只剩一行或一列,此時就不用繼續往下遞迴了。