Problem
給定一個 n x m 的網格,現在要紮營於格子上,但是每一格的高度不同,希望使用 k 個格子,他們可以藉由上下左右四格相連,找一種方案,使得最低、最高紮營高度差最小。
Input
|
|
Output
|
|
Solution
由於高度介於 0 到 100 之間,考慮窮舉最低紮營處的高度 l。採用掃描線的方式,依序加入高度較低的地點,直到其中一個連通子圖的節點總數大於等於 k。
為了加速,使用并查集來完成合併連通子圖。
|
|
給定一個 n x m 的網格,現在要紮營於格子上,但是每一格的高度不同,希望使用 k 個格子,他們可以藉由上下左右四格相連,找一種方案,使得最低、最高紮營高度差最小。
|
|
|
|
由於高度介於 0 到 100 之間,考慮窮舉最低紮營處的高度 l。採用掃描線的方式,依序加入高度較低的地點,直到其中一個連通子圖的節點總數大於等於 k。
為了加速,使用并查集來完成合併連通子圖。
|
|
給定一種特殊的騎士走法,請問在 n x m 格子上,從 (x, y) 到 (a, b) 的步數情況,走訪時不能重複經過相同點。
若能恰好在質數步抵達,輸出最少的步數。如不是質數,輸出合數的最少步數。都還是不行則輸出無法抵達。
|
|
|
|
這題麻煩的地方在於恰好在質數抵達,那麼考慮使用 IDA 來完成,在搜索時發生不是在質數步數抵達回傳無解,繼續迭代加深。估價函數為當前座標 (x, y) 到 (a, b) 的最短距離。
在做 IDA 之前,使用 Bfs 查看移動所需步數,若恰好是質數則直接輸出答案,若保證無法抵達終點,輸出無解。最後再進行 IDA 搜索,來加快處理程序。
根據測試,使用的質數步數不大於 11。
|
|
給一個只有加法、乘法和括弧的運算式,在不改變最後的答案下,有多少種不同的運算順序 (不同的 parse tree)。
|
|
|
|
類似矩陣鏈乘積的 O(n^3) 解法。
dp[l, r]
表示表達式 exp[l, r]
正確的方法數。當運算式存在加法時,不能拆分乘法運算。只剩下乘法運算時,才能拆分乘法運算。
|
|
瘋狂的島嶼上有 n 個野蠻人、m 個山洞,山洞呈現環狀分佈。
每個野蠻人一開始各自在自己的洞窟 Ci,每隔一天就會移動到下 Pi 個山洞,在島上待 Li 天後就會死亡。
兩個野蠻人若剛好移動到相同洞窟,則會發生爭吵,請問至少要幾個洞窟,才能不發生爭吵。
|
|
|
|
窮舉洞窟數量 m,檢查是否存在爭吵。
檢查任兩個野蠻人 i, j 是否會在生存時間內相遇,假設會在第 k 天相遇,滿足公式
|
|
將公式整理後
|
|
檢查 k 最小為多少,使得等式解存在。
套用擴充歐幾里德算法,得到 ax + by = gcd(x, y)
的第一組解 (a, b)
,其 a, b 的參數式為
|
|
最小化 a 參數,滿足 a >= 0
,隨後檢查可行解即可。
|
|
有隻猴子在樹間,每一棵樹有平行的分支,猴子可以在兩棵樹的分支端點跳躍,並且跳躍距離不超過歐幾里德距離 K
,並且跳躍的時候只能跳端點的直線上,同時不能撞到其他分支,否則視如跳躍失敗。
猴子從樹幹走到分支端點、端點走到樹幹是需要計算步行花費,請問從第一棵樹走到最後一棵樹,最少的步行花費為何。
|
|
|
|
分支數量很少,直接暴力嘗試跳躍的可行性。使用外積解決線段交問題,隨後計算跳躍的最少花費,記錄狀態 dp[i]
表示從第一棵樹走到第 i 棵樹的最少步行成本。
特別小心當跳躍都無法時,可以走在地面上,由於這一點掛了好多 WA。
|
|
給一個橢球的三個參數,一刀縱切橢球,問切割橢球的截面積為何。
|
|
|
|
回顧積分公式,得到橢圓面積。將橢球固定一個參數,調整計算截面積。公式如代碼中所附。
$$\frac{x^2}{a^2} + \frac{y^2}{b^2} = 1 \\ \text{area } = ab\pi \\ \frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} = 1 \\ \frac{x^2}{(a \sqrt{1 - z^2 / c^2})^2} + \frac{y^2}{(b \sqrt{1 - z^2 / c^2})^2} = 1 \\ \text{cross-sectional area} = ab (1 - z^2 / c^2) \pi \\$$
|
|
給予 n 種酒瓶,每一種酒瓶有其裝酒的容積上下限 [min, max]
毫升,請問將 m 公升的酒裝入酒瓶,最後剩餘的最少量為多少。
每一種酒瓶可以無限使用。
|
|
|
|
這一題需要剪枝,無法單純地運行背包 dp,單純的背包 dp 很容易造成 TLE。
發現到只考慮使用一種酒瓶,那麼當酒量大於某個定值後,保證都能裝完。假設使用單一酒瓶的數量為 k 個以上時,能裝出所有量,則能覆蓋的區間為
|
|
當第 k+1 個區間的左端點小於第 k 個區間的右端點時,可以得到接下來的所有區間都會發生重疊。推導得到 (k+1)*min >= k*max
最後條件 k >= min / (max - min)
。
滿足保證能裝出,直接輸出答案 0
,否則做背包 dp。
|
|
依序背單字,下一個單字中要出現當前單字為 substring 的情況,每一個單字都有各自的權重,求背一次能得到的最高權重總合為多少。
如範例輸入背的順序為 a -> ab -> abb -> abbab
答案為 1 + 2 + 3 + 8 = 14
。
|
|
|
|
這一題的測資有問題,輸入中出現非小寫字母,導致存取發生錯誤,部分程序沒有考慮這一點,居然就通過了?
一群人 Invalid Memory Access 通過,而我因寫法比較不同成了 RE 下亡魂,測試數據格式錯誤啊!坑爹啊,害我掛載好多 assert 抓哪裡溢出 …
原本想說是一道有趣的 AC 自動機複習,將 fail 指針 (suffix link) 整理成另一棵樹,對其 fail tree 壓樹 (走訪),套上線段樹等數據結構,就能支持多字串匹配的數據查找。當匹配時將會一直攀爬 fail 指針,最後爬到 root,中間經過的節點都是匹配的字串,也因此單看 fail 指針,也肯定是 tree。
在走訪時,會匹配 fail link 上的所有節點 (都是其 suffix string)。dp[i]
表示使用第 i 個字串為背單字序列結尾的最大權重,則 dp[i] = max(dp[j]) + w
,其中滿足 j < i 且 word[j] 是 word[i] 的 substring。
窮舉第 i 字符串的後綴匹配節點,找尋匹配節點藉由 fail link 到 root 上節點的最大值 (max(dp[j])
)。
利用線段樹完成區間最大值更新、單點查詢 (找尋節點到 root 的最大值,更新一個點的權重時,相當於作區間最大值更新,藉由壓樹其子樹被表示成區間)。
|
|
進行天文觀測,天空上有 n 個流星,以及拍攝的區域。
給定每一個流星的起始位置與速度,請問在哪一個時刻可以拍到最多顆流星在拍攝區域內部。
|
|
|
|
將每一個流星進入和離開拍攝區域的時間求出,並且組合成 (enter_time, 1), (leave_time, -1) 的方式,根據時間由小排到大,利用掃描線算法統計累計的最大值即可。
求流星進出區域的時間,可以將 x, y 座標分開考慮,對進入時間取最大值、離開時間取最小值。
|
|
一筆畫完成一個簡單多邊形,請問有多少個區域。
|
|
|
|
利用尤拉公式$V - E + F = 2$ 來完成,藉由線段交找到所有頂點集合,去除掉重複點後,檢查邊的數量,如此一來就可以找到面的數量。
特別小心共線計算。
|
|