Luogu 🟡 P4653 [CEOI 2017] Sure Bet
題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
🔗 P4653 [CEOI 2017] Sure Bet
Problem Statement
題目簡述
有 組燈泡,每組各有一顆 A 類與一顆 B 類燈泡,權值分別為 。
你可以任意挑選一些燈泡,每挑一顆就要付出 的代價。
最後系統會在 A 類與 B 類之間隨機選一種點亮,你只能拿到被點亮那一類、且你有挑選到的燈泡權值總和。
也就是說,若你挑了若干顆 A 與若干顆 B,最終保證收益為:
請最大化這個「最小可能收益」。
Constraints
約束條件
- 輸入實數最多到小數點後四位
- 需輸出答案到小數點後恰好四位
思路:排序後只補較小的一側
1. 先把「怎麼挑」化成前綴問題
雖然輸入是成對給出 ,但題目並沒有要求同一組的兩顆燈泡必須一起選或一起不選。也就是說,A 類與 B 類的挑法其實彼此獨立,可以分開考慮。
假設我們最後決定:
- 從 A 類挑 顆
- 從 B 類挑 顆
那麼在這個前提下,最好的選法一定是:
- A 類挑權值最大的前 顆
- B 類挑權值最大的前 顆
理由很直接:既然挑選顆數已經固定,當然應該在各自類別中拿權值最高的那些燈泡,任何不是前幾大的選法都只會更差。
因此我們可以先把兩個陣列各自由大到小排序,並令:
- :A 類前 大的總和
- :B 類前 大的總和
此時若選的是這兩個前綴,保證收益就是:
原題因此被改寫成一個更乾淨的目標:
在所有 中,最大化這個式子。
原題表面上像是在做組合選擇,但一旦固定了 A、B 各挑幾顆,最優集合就唯一地變成排序後的前綴,因此問題本質上只剩下狀態 。
2. 為什麼只需要補目前較小的那一側?
假設目前在某個狀態 。
若此時:
那麼當前的最壞情況就由 A 類決定,因為
這時如果不去補 A,而是再多拿一顆 B 類燈泡,會發生什麼?
- 不會變大,因為較小者仍然是
- 但代價會多
也就是說,答案只會變差,不可能變好。
所以當 時,若還想讓答案上升,唯一可能有幫助的做法就是補 A 類下一顆;反過來,若 ,就只能補 B 類。
至於兩者剛好相等時,先補哪一邊都不影響正確性;。
目前較小的一側決定了最壞收益,因此只有補那一側,才有機會把 往上推;補較大的一側只是在白白增加成本。
3. 何時可以停止?
只要目前較小的那一側還有下一顆可拿,就仍然有機會把 拉高,因此值得繼續往前走。
但如果:
sa < sb且 A 已經拿完- 或
sb < sa且 B 已經拿完
那就代表「決定最壞收益的那一側」已經沒有辦法再提升了。這時如果硬要繼續補另一側,只會讓挑選成本增加,而 仍然不會變大,所以可以直接停止。
程式中的 while 條件,表達的正是這個想法:
- 兩邊都還有元素時,當然可以繼續
- 若其中一邊先用完,只有在「尚未用完的那一邊正是較小側」時才值得繼續補
不是「任一邊用完就停」,而是「決定答案的較小側用完才停」。
4. 正確性直觀總結
對任意狀態 :
- 若 ,任何只增加 的做法都不可能讓答案更好
- 若 ,任何只增加 的做法都不可能讓答案更好
換句話說,從任意狀態出發,唯一可能通往更好答案的方向,就是擴張當前較小的那一側。雙指標所做的事,就是沿著這條「所有可能有貢獻的路徑」一路掃過去,因此不會漏掉最優解。
複雜度分析
- 時間複雜度:
- 空間複雜度:
Code
1 | def solve(): |





![Luogu 🔵 P1578 [WC2002] 奶牛浴场](https://i.gdst.dev/cover/P1578.webp)
![Luogu 🟡 P3467 [POI 2008] PLA-Postering](https://i.gdst.dev/cover/P3467.webp)
![Luogu 🟡 P7910 [CSP-J 2021] 插入排序](https://i.gdst.dev/cover/P7910.webp)
![Luogu 🟡 P4653 [CEOI 2017] Sure Bet](https://i.gdst.dev/cover/P4653.webp)


![Luogu 🟢 P2216 [HAOI2007] 理想的正方形](https://i.gdst.dev/cover/P2216.webp)
![Luogu 🟢 P2671 [NOIP 2015 普及组] 求和](https://i.gdst.dev/cover/P2671.webp)



