來自《挑戰編程》和《算法競賽入門經典(第2版)》
Programming Challenges
- 因爲這道題的測試用例有錯誤,詳見這裏3樓的評論
- 浮點數的題目我一向沒有好感
- 網上給出了很多貪心的解法,還有爲數不多的動態規劃解法,但是我沒想明白
習題5.9.3 701 The Archeologists’ Dilemma
- 如果嘗試枚舉
E
的話那麼很快程序就超時了 - 雖然我也感覺不應該暴力枚舉求解,應該用對數,但是沒想出來那個不等式是怎麼來的(
N * 10^K < 2^X < (N + 1) * 10^K
)。
習題6.6.2 10213 How Many Pieces of Land ?
- 想了好久,還是去網上查了一下,可以直接根據平面歐拉公式(
F = E - V + 2
)來算,因此這道題中區域總數爲1 + C(n, 2) + C(n, 4)
- 需要使用大數運算
- 我感覺面試題不會有這種東西吧?
- 根據書上關於Catalan數的提示,可以得到遞推公式爲:
S(n ,d) = sum(S(i, j) * S(n - 2 - i, d)(0 <= i <= n - 2, 0 <= j <= d - 2))
+ sum(S(i, d - 1) * S(n - 2 - i, j)(0 <= i <= n - 2, 0 <= j <= d))
- 根據第一個括號閉合的位置將表達式分成兩部分,左邊被括起來的表達式深度分成兩部分來考慮:長度從
0
變化到n - 2
,深度從0
變化到d - 2
,這樣被括起來後最大深度爲d - 1
,所以右邊未被括起來的部分深度必須爲d
,長度爲n - 2 - i
;長度從0
變化到n - 2
,深度爲d - 1
,這樣被括起來後深度爲d
,所以右邊深度的變化範圍從0
到d
。這樣每計算一項需要2重循環,計算所有的就需要4重循環 - 通過觀察遞推公式,可以將部分項合併,第一項的
S(i, j)
中j
的範圍是0 <= j <= d - 2
,而第二項中正好有S(i, d - 1)
,這樣合併後就可以得到:
S(n, d) = sum(S(i, j) * S(n - 2 - i, d)(0 <= i <= n - 2, 0 <= j <= d - 1))
+ sum(S(i, d - 1) * S(n - 2 - i, j)(0 <= i <= n - 2, 0 <= j <= d - 1))
。 - 因爲
j
只出現在乘積項的一側,而i
出現在乘積項的兩側,所以可以對j
進行優化,記T(i, d - 1) = sum(i, j)(0 <= j <= d - 1)
,表示長度爲i
,深度不超過d - 1
的表達式的個數,這樣遞推公式就又變成了:
S(n , d) = sum(T(i, d - 1) * S(n - 2 - i, d)(0 <= i <= n - 2))
+ sum(S(i, d - 1) * T(n - 2 - i, d - 1)(0 <= i <= n - 2))
- 然後根據剛纔對
T
的定義,將S
代換爲T
,可得:
S(n, d) = sum(T(i, d - 1) * (T(n - 2 - i, d) - T(n - 2 - i, d - 1)))(0 <= i <= n - 2)
+ sum((T(i, d - 1) - T(i, d - 2)) * T(n - 2 - i, d - 1))(0 <= i <= n - 2)
= sum(T(i, d - 1) * T(n - 2 - i, d) - T(i, d - 2) * T(n - 2 - i, d - 1))
- 第一項表示長度爲
i
、深度不超過d - 1
每一項用括號括起來後和長度爲n - 2 - i
、深度不超過d
進行組合,最後可得長度爲n
,深度不超過d
的表達式數量,就是剛剛定義的T(n, d)
,後邊一項正好爲T(n, d - 1)
。 - 廢了一大圈勁,終於從樸素的想法推到正確的解題方法了。😦
習題6.6.5 10247 Complete Tree Labeling
- 開始的時候一直思考如何從二層的二叉堆遞推三層的二叉堆,然後從二叉堆怎麼遞推三叉堆,但是發現一種固定編號的二層二叉堆,變成三層的過程中會破壞二層的編號,所以從具體的某一種編號方式應該是無法遞推
- 看了一下網上的答案,如果不考慮二層的排列具體用了哪幾個數字,只考慮用可以得到多少種二層的排列,那麼在變成三層的時候,根一定是最小的
1
,然後從把剩下的數字平均分成k
份,每一叉用一份,再用乘法原理進行計算
習題6.6.6 10254 The Priest Mathematician
- 這明明是一個遞推題,公式也很好寫,
f(n) = min(f(k) + 2^(n - k) - 1)(0 <= k < n)
,但是故意把數值搞大了,然後高精度計算也會超時 - 其實它的一階差分序列是有規律的,我佛了 😦
- 這題不能枚舉,整數規劃使用割平面好像有解法,但是也不能直接套用,看網上說用凸包,這是個啥?
習題8.6.8 10270 Bigger Square Please…
- 這道題看起來就賊難
- 搜索肯定是能解的。首先要把
N ^ 2
表示爲小於N
的數的平方和,然後根據這種表示方式,再嘗試進行覆蓋,最終取數量最小的那個 - 根據書上的提示,深搜可以先取大的,或者是否可以用遞推來解決?我也不知道
- 第二層深搜優先放置大的,大的本身位置就少,這樣或許可以剪枝?
習題10.5.7 10249 The Grand Dinner
- 貪心或者最大流可解
習題10.5.8 10092 The Problem With the Problem Setter
- 運籌學中的分配問題,或者稱爲指派問題,我記得郭強老師的《運籌學原理與算法》中給出了使用類似Floyd算法的求解方法
- 該算法爲郭老師研究發明,可惜的是沒什麼人知道
算法競賽入門經典(第2版)
習題3-12 10189 Floating-Point Numbers
- 同樣是浮點數的題目
- 一道根據題意模擬的題目,寫起來可能會很複雜
例題5-10 207 PGA Tour Prize Money
例題5-11 814 The Letter Carrier’s Rounds
- 兩道根據題意模擬的題目
- 看起來簡單,可能會有坑和難調的bug
- 輸出格式複雜
- 浮點數的簡單題目,但是還是先跳過