AtCoder 🌈 AWC0096D Hiking and Rest
🔗 AWC0096D Hiking and Rest
Problem Statement
題目簡述
高橋從海拔 開始爬山,路線分成 段。通過第 段後,海拔會增加 ;若變化後小於 ,則海拔會被修正為 ,也就是新海拔為 。
爬山途中必須恰好使用一次纜車。使用纜車時,當前海拔 會立刻變成 。纜車可以在第 段前、任兩段之間,或第 段後使用。求最優使用時機下,完成所有路段後的最小海拔。
Constraints
約束條件
- 所有輸入皆為整數
思路:狀態機DP
這題涉及一個典型套路:操作「恰好一次」,且操作位置可以插在任意兩個元素之間。直接枚舉纜車使用位置,再從頭模擬到尾,會是 ,無法承受。
關鍵在於,走到某個位置後,對未來有用的資訊其實很少。不妨定義:
- :走完前 段,且尚未使用纜車時,能得到的海拔。
- :走完前 段,且已經使用纜車時,能得到的最小海拔。
其中 沒有分支,因為纜車還不能用; 則把「纜車在哪個位置使用」這個選擇壓縮成一個最小值。
貪心的正確性
高度轉移 對 是單調不減的。也就是說,在纜車已使用的情況下,當前海拔越低,走完後面路段也不會變得更差。因此只保留最小可能海拔是安全的。
狀態轉移
先看「尚未使用纜車」的狀態。走完第 段後只能照普通爬山規則更新:
再看「已經使用纜車」的狀態。它有兩種來源:
- 纜車早在之前就用過,現在只是繼續通過當前路段。
- 纜車在當前路段之後使用,於是從尚未使用纜車的海拔立刻折半。
對應轉移為:
第一項表示「之前已經使用纜車,現在走第 段」;第二項表示「先正常走完第 段,再立刻使用纜車」。兩者取較小值,就是走到目前位置後、纜車已使用時的最佳海拔。
滾動陣列壓縮
實作時不需要真的開二維陣列。因為每次轉移只依賴上一段的狀態,所以用兩個變數壓縮:
h0對應目前的 ,初始為 。h1對應目前的 ,初始為 ,表示出發前已經使用纜車。
每讀到一段變化量,就先更新尚未使用纜車的高度,再更新已使用纜車的最小高度。
由於在第 段前就可以使用纜車,所以初始值 ,表示「出發前已經使用纜車」。
複雜度分析
- 時間複雜度:
- 空間複雜度:,因為程式保存了整個變化序列;若讀入後直接迭代原序列,也可視為只需 額外狀態
Code
1 | def solve(): |
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus





