codeUp 2031 To fill or not to fill 复杂贪心
2031: To Fill or Not to Fill
時(shí)間限制:?1 Sec??內(nèi)存限制:?32 MB
提交:?599??解決:?132
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: Cmax?(<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg?(<=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: Pi, the unit gas price, and Di?(<=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
?
題意就是從起點(diǎn)到終點(diǎn)有很多的加油站 每個(gè)加油站有距離起點(diǎn)的距離和單價(jià)?我們從起點(diǎn)開車到終點(diǎn) 開始油量為0 要盡可能走到終點(diǎn) 問所求的最小花費(fèi)是多少?如果走不到終點(diǎn) 就輸出最遠(yuǎn)距離。
一開始給出油箱大小,到終點(diǎn)的距離,還有每單價(jià)油可以走的里程數(shù),以及加油站的信息
?
分析:
由于這個(gè)問題邏輯比較復(fù)雜 可以先研究樣例
假設(shè)汽車從起點(diǎn)S到終點(diǎn)E必須通過加一次油到達(dá) 可達(dá)范圍內(nèi)有多個(gè)價(jià)格不一的加油站?
如果可達(dá)范圍內(nèi)有更便宜的G 我們要選擇那個(gè)加油站續(xù)命 先加夠到這個(gè)加油站G的油 在到G處加新的油 這樣就相當(dāng)于從起點(diǎn)到G再到終點(diǎn)的松弛 可以通過這個(gè)加油站把后面的路程的花費(fèi)給減小“松弛”掉??
如果選擇某個(gè)并不是選擇可達(dá)范圍內(nèi)最靠前的更便宜的加油站去加油站
如果選擇了一個(gè)較遠(yuǎn)的,花費(fèi)更大的站A 那么就必然導(dǎo)致起點(diǎn)加油變多花費(fèi)變多,從A站新加的油到終點(diǎn)的這段距離花費(fèi)變多 雖然路程變小 從全局來看 兩種不同的選擇花費(fèi)不同的路段里 第二段從G到A花費(fèi)變多 從A到終點(diǎn)E花費(fèi)也變多?從而導(dǎo)致全局花費(fèi)更大
如果選擇了一個(gè)較近的花費(fèi)更大的站B 那么從起點(diǎn)S到B花費(fèi)不變 那么從B到G花費(fèi)變多 從G到終點(diǎn)花費(fèi)也變多 ?從而導(dǎo)致全局更大的花費(fèi)
所以在當(dāng)前站 選擇可達(dá)范圍內(nèi)最近的且更便宜的能夠帶來更小的局部最優(yōu) 從而獲得更小的全局花費(fèi)
如果沒有更便宜的?
那么就要在初始S加滿 這樣才能盡可能少加更貴的油 從而減小花費(fèi)
那么選擇所有比初始S貴的里面最便宜G的? 那么從S到G花費(fèi)起點(diǎn)S的油錢 從G到終點(diǎn)E 再化一部分新加的G站油錢 如果不是這樣選 得到的花費(fèi)只會(huì)更大 怎么呢?
我們來看 這種情況下 續(xù)命油的油量是確定的 因?yàn)槲仪懊婕訚M了?
如果選擇一個(gè)更近的站A但并不是可選加油站中最便宜的 那么從起點(diǎn)S到A花費(fèi)不變,從A到G花費(fèi)不變 但到終點(diǎn)需要加一次油 這時(shí)需要加的油會(huì)更貴一點(diǎn)(A站油錢) 從而全局花費(fèi)更大
如果選擇一個(gè)更遠(yuǎn)的站B但并不是可選加油站中最便宜的 那么起點(diǎn)到G花費(fèi)不變 G到B花費(fèi)不變?B到終點(diǎn)E 需要續(xù)一次油 花費(fèi)變大(B站油錢)
所以在這種?分支下 我們也要選擇貴中最便宜的那個(gè)去加油 從而獲得全局最優(yōu)
我們要找的續(xù)命的加油站 必須是可達(dá)范圍里最便宜的 只有這樣 才能通過這個(gè)最便宜的加油站 獲取盡可能便宜的局部最優(yōu)花費(fèi) 這樣再去選?
你有可能會(huì)有疑問
如果我們想G走著走著發(fā)現(xiàn)一個(gè)可達(dá)范圍內(nèi)更便宜站P的怎么辦 即便如此 我們也要先到G站 看看能不能不加油直接走到P站 不過不可能! 因?yàn)镻是G站決策之前的可達(dá)范圍之外的站 必然不可能不加油走到P站 所以我們有必要中間續(xù)油 那么續(xù)油的話 只能在G續(xù)油 因?yàn)镚是最相對(duì)便宜的 我們只有先到了G再看看需要續(xù)多少油到更便宜的加油站去 如果沒有更便宜的加油站 則繼續(xù)選擇可達(dá)范圍內(nèi)所有更貴的里面最便宜的? 所以整個(gè)過程就是
局部最優(yōu)+局部最優(yōu)+...+局部最優(yōu) = 全局最優(yōu)
?
于是這個(gè)問題的邏輯大致就是如此 對(duì)每個(gè)加油站執(zhí)行相同的邏輯 我們發(fā)現(xiàn)這樣的話就是貪心策略 每到一個(gè)加油站 在能到達(dá)的范圍內(nèi)選擇局部最優(yōu)策略 這樣走下來就能得到全局最優(yōu)策略 如果在加油站不進(jìn)行局部最優(yōu)的策略 那么就必然導(dǎo)致花費(fèi)變大
如果起始點(diǎn)沒有加油站 那么就輸出0 因?yàn)榧硬坏接捅厝蛔卟怀鋈?/p>
否則:
看看加滿油的話 能到達(dá)的范圍內(nèi) 有沒有加油站?
? ? ? ? ? ? ? ? ? ? ?如果沒有 那么就加滿油盡可能跑 能跑多遠(yuǎn)就輸出多遠(yuǎn)
? ? ? ? ? ? ? ? ? ? ?如果有加油站 看看有沒有一個(gè)加油站是他能到達(dá)的范圍內(nèi)且離當(dāng)前點(diǎn)比較近的?我們?cè)O(shè)此站位G站
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如果有 我們就買剛好到G站的油量:因?yàn)榈搅薌站買油可以得到更便宜的價(jià)格 從而盡可能的得到更小的花費(fèi)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如果沒有 全都是比當(dāng)前站更貴的加油站 那么就要從貴中選一個(gè)最便宜的設(shè)為H站 我們要走到那里繼續(xù)買油才能盡可能的減小花費(fèi) 注意 這時(shí)要從當(dāng)前站加滿油 因?yàn)镠站的油是更貴的 但是又不能因?yàn)橛唾F而不走 還是要盡可能往前走的 這時(shí)如果不從H站買 從其他站買 只會(huì)導(dǎo)致更多的花費(fèi)??所以我們要盡可能少的從H站買油 我們到了H站要站在H站的位置考慮更優(yōu)的花費(fèi)時(shí) 再?gòu)腍站買油 故從當(dāng)前站要加滿油 然后去向H站???
?
由于本題需要維護(hù)的參數(shù)比較多 邏輯比較復(fù)雜 還是要想清楚邏輯后 把變量寫的可讀性高點(diǎn) 才能少出bug
時(shí)間復(fù)雜度:O(n^(所能到達(dá)的范圍中的加油站個(gè)數(shù)))<O(n^2)<1000ms
?
#include<cstdio> #include<cstring> #include<iostream> #include<map> #include<cmath> #include<algorithm> #include<set> #include<vector> #include<climits> #define Equal(a,b) (fabs((a)-(b))<=eps) #define LessEqu(a,b) (((a)-(b))<=eps) #define Lessthan(a,b) (((a)-(b))<-eps) #define Morethan(a,b) (((a)-(b))>=eps) #define MoreEqu(a,b) (((a)-(b))>=-eps) const double eps = 1e-5; using namespace std; typedef long long ll; struct station{double cost;double dis; }S[510]; bool cmp(station a,station b){return Lessthan(a.dis,b.dis); } int main(){double c,dis,avg;int sta;ios::sync_with_stdio(0);cin>>c>>dis>>avg>>sta;for(int i=1;i<=sta;i++){cin>>S[i].cost>>S[i].dis;}double Lowest = S[1].cost;for(int i=2;i<=sta;i++){if(Lessthan(S[i].cost,Lowest)){Lowest = S[i].cost;}}sort(S+1,S+1+sta,cmp);if(!Equal(S[1].dis,0.0)){cout<<"The maximum travel distance = 0.00"<<endl;return 0;}bool f=0;S[sta+1].cost = 0,S[sta+1].dis = dis;double exp=0,canadd=c,distans=0,cut=0,unit=c;double costoil,oil = 0;bool fal = 0;for(int i=1;i<sta+1;i++){oil = (distans-S[i].dis)/avg;double Maxlim = S[i].dis + c*avg;double CMP = S[i].cost;int j,u=i;for(j=i+1;j<=sta+1&&LessEqu(S[j].dis,Maxlim);j++){if(Lessthan(S[j].cost,CMP)){CMP = S[j].cost;u = j;break;}}if(u==i&&j==i+1){//后面沒加油站distans = Maxlim;fal = 1;break;}if(u!=i){//有個(gè)更便宜的unit = (S[u].dis-distans)/avg;//減去的是什么很關(guān)鍵exp+=S[i].cost*unit;// canadd = unit;distans = S[u].dis;i = u-1;oil += unit;costoil = unit;continue;}//如果后面的都是比自己貴的CMP = S[i+1].cost;u = i+1;for(int j=i+2;j<=sta+1&&LessEqu(S[j].dis,Maxlim);j++){if(LessEqu(S[j].cost,CMP)){//盡可能少買 也就是盡可能遠(yuǎn)CMP = S[j].cost;u = j;}}canadd = c-oil;distans += (canadd)*avg;exp+=canadd*S[i].cost;costoil = (S[u].dis-S[i].dis)/avg;oil=c;i = u-1;}if(fal)printf("The maximum travel distance = %.2f\n",distans);else printf("%.2f\n",round(exp*100)/100);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的codeUp 2031 To fill or not to fill 复杂贪心的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做免费的EDM,EmailCar看中的是
- 下一篇: 罗技 GHUB驱动的官方下载网址