1. 程式人生 > >PAT 1033 To Fill or Not to Fill (25分) 貪心思想

PAT 1033 To Fill or Not to Fill (25分) 貪心思想

### 題目 With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go. **Input Specification:** Each input file contains one test case. For each case, the first line contains 4 positive numbers: C​max​​ (≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; D​avg​​ (≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: P​i​​ , the unit gas price, and D​i​​ (≤D), the distance between this station and Hangzhou, for i=1,⋯,N. All the numbers in a line are separated by a space. **Output Specification:** For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X where X is the maximum possible distance the car can run, accurate up to 2 decimal places. **Sample Input 1:** 50 1300 12 8 6.00 1250 7.00 600 7.00 150 7.10 0 7.20 200 7.50 400 7.30 1000 6.85 300 **Sample Output 1:** 749.17 **Sample Input 2:** 50 1300 12 2 7.10 0 7.00 600 **Sample Output 2:** The maximum travel distance = 1200.00 ### 題目解讀 題目大意:汽車從杭州出發可以通過高速公路去任何城市,但是油箱的容量是有限的,路上有很多加油站,每個加油站的價格不同,為汽車設計一個從杭州到終點的最便宜的加油策略。 輸入:第一行:`Cmax`表示油箱最大容量,`D`表示杭州到目的地的距離,`Davg`表示平均每單位的汽油可以讓汽車行駛的距離,`N`表示途中加油站的數量;接下來 `N` 行:給出給個加油站的單位油價`Pi`和杭州(起點)到這個站點的距離`Di`。 輸出:求汽車從杭州到終點的最少花費(**精確到兩位小數**)。如果不能夠到達,就輸出汽車能夠行駛的最大距離(**精確到兩位小數**)。 ### 思路分析 核心思想:**貪心演算法**(每次尋找**區域性最優**,在最便宜的加油站加最多的油)。 前期準備: - 最終輸出無論是距離還是價格都要求精確到兩位小數,雖然從給出的輸入資料來看,距離、郵箱容量等好像都是整數,但為了操作方便,避免運算過程精度丟失,我們全都用`double`儲存。(再說了,它給出的資料說不定就是坑你的呢?) - 設定`結構體陣列`儲存每個加油站的單價和到杭州的距離。 - 按照到杭州的距離對結構體陣列**排序**,因為輸入是無序的。 - 排序完**判斷第1個結構體到杭州的距離是否為0**,也就是說最近的加油站是不是在起點。因為題目說了假定剛開始郵箱沒有油,那麼如果起點處沒有加油站,就比欸想開車了,直接輸出並返回吧。 貪心**核心**:怎麼實現每次都做出區域性最優的選擇? 對於任意一個站點:如果我們在這個站點加滿油,那麼最多就可以跑`cmax*davg`的距離,我們對**這個距離段中遇到的加油站**情況進行分析: - 按順序遍歷`【當前位置,當前位置+cmax*davg】`中的所有加油站,如果某個加油站的收費**低於**當前站點,那麼我就在當前站點加油,跑到那個站點去,加多少呢?就加能**恰好讓我到達那個加油站**的油。這樣我去那個站點加油就能更便宜。 - 如果當前站點後面有不止一個站點更便宜,怎麼選擇?比如我現在在`A`,價格是`10`,後面是 `B` 價格`9`, 後面是`C` 價格`8`, 我**先找到的是B,那我就退出本次迴圈,剛好加油跑到B去**,在`B`處重新繼續分析。為啥不直接加油去`C`,如果從當前位置直接加油去`C`,那麼`BC之間`的花費單價是當前加油站的價格也就是`10`,但我如果先去了`B`,那麼`從B到C`的油價就是`B`處的價格`9`,顯然更便宜。這樣才滿足區域性最優。 - 如果當前位置後面沒有更便宜的加油站呢? - 如果**我在當前位置最多能達到的最遠距離超過了終點**,那麼我直接加油跑到終點,因為後面的站點只會更貴。 - 如果我不能直接到終點,那麼我肯定是需要加油的,那我就找儘可能地找比較便宜的那個加油站,**在當前加油站加滿油**之後過去。既然沒有比當前更低價格的了,就讓油箱加到最大值,這樣能保證利益最大化,保證最大的距離使用的是便宜的油。 - 如果當前位置不能直接到達終點,並且後面沒有加油站了呢?那麼肯定不能到達中終點了,只能到達`當前位置+cmax*davg`,也就是說在當前位置加滿,能跑多遠是多遠。 **總結:** - 當前位置能到達的範圍中如果**存在**更便宜的加油站,就加合適的油剛好到達那個加油站。 - 如果**不存在**更便宜的,但是當前位置**能直接到達終點**,那就加合適的油到達終點。 - **不存在**更便宜的,並且**不能直接到終點**,找到可達的加油站的相對而言最便宜那個,在**當前位置加滿油**,然後去那個站點。 - 當前位置**不能到終點**,並且後面**沒有加油站**了,輸出能到達的最大距離。 ### 程式碼 ```cpp #