2、問題描述:
乙個旅行社需要估算乘汽車從某城市到另一城市的最小費用,沿路有若干加油站,每個加油站收費不一定相同。旅遊預算有如下規則:若油箱的油過半,不停車加油,除非油箱中的油不可支援到下一站;每次加油時都加滿;在乙個加油站加油時,司機要花費2元買東西吃;司機不必為其他意外情況而準備額外的油;汽車開出時在起點加滿油箱;計算精確到分(1元=100分)。編寫程式估計實際行駛在某路線所需的最小費用。
3、輸入
第一行為起點到終點的距離(實數) 第二行為三個實數,後跟乙個整數,每兩個資料間用乙個空格隔開。其中第乙個數為汽車油箱的容量(公升),第二個數是每公升汽油行駛的公里數,第三個數是在起點加滿油箱的費用(精確到分),第四個數是加油站的數量。(〈=50)。接下去的每行包括兩個實數,每個資料之間用乙個空格分隔,其中第乙個數是該加油站離起點的距離,第二個數是該加油站每公升汽油的**(元/公升)。加油站按它們與起點的距離公升序排列。所有的輸入都有一定有解。
4、輸出
共兩行,每行都有換行 第一行為乙個實數和乙個整數,實數為旅行的最小費用,以元為單位,精確到分,整數表示途中加油的站的n。第二行是n個整數,表示n個加油的站的編號,按公升序排列。資料間用乙個空格分隔,最後乙個資料後也輸出空格,此外沒有多餘的空格。
5、樣例
輸入樣例
516.3
15.7 22.120.87 3
125.41.259
297.91.129
345.20.999
輸出樣例
38.09 1 2
6、問題解析
1)這個問題的關鍵就在於找到「狀態」,這個狀態就是min[i],從i點出發到終點的最小費用;
2)其次就是需要意識到這個狀態是乙個逆序的計算,也就是從第n個加油站開始,把起點當成第0個;
3)還有乙個初始化問題,對於能夠在滿油狀態下直接到達終點的,初始化為0;
4)接下來就是狀態的變化了,在計算第 i 個加油站最小費用min[i]的時候,需要用到之前計算出的min[j],理論上i
5)在計算過程中還需要考慮限制條件,油箱過半並且可以到達j+1站,就不在j加油,這樣排除一部分j;
6)最後是加油站的追蹤,對於每個i,都只有乙個最優的j,所以令i=j,一層層追蹤就行了。
這個問題對我來說是很麻煩了,有附加的考慮條件,要求的解也是具體方案,還有輸入輸出也算是比較麻煩的。
7、下面是具體的**,已經提交驗證過:
#include#includeusing namespace std;
int main()
//從第n個加油站開始,逆序向前,把起點當做第0個加油站
i = n;
while (((dis_all - dis[i]) / mile_per_oil) <= cap)
double tmp;//輔助的**變數,一開始定義成了int,結果發生了截斷。。。。。
int k;//記錄此時的加油點
for (; i >= 0; --i) {//開始迴圈
min[i] = int_max;
for (j = i + 1; j < n + 1 && (dis[j] - dis[i]) / mile_per_oil <= cap; ++j){//從i點滿油狀態下可以到達的點中進行篩選,如果到j點後油量超過一半並且能到到達j+1點,就不加油,continue
if (j == n) {
if (((dis[j] - dis[i]) / mile_per_oil)
vijos1476 旅遊規劃 動態規劃
傳送門 題解 我是這麼做的,首先第一遍求出每個點向下的不相交的最長鏈和次長鏈,這樣兩條鏈拼起來就是就是過這個點 不包含他的父親的情況下 的最長鏈。在這些最長鏈中取max就可以得到直徑。然後乙個點在直徑上,要麼他本身就在已經求出的最長鏈上 就是從這個點出發的最長 次長鏈 直徑長度 要麼如果這個點在某一...
動態規劃 金明的預算方案
題目傳送門 題目描述 金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n元錢就行 今天一早,金明就開始做預算了,他把想買的物品分為兩類 主件與附件,附件是從屬於某個主件的,下表...
codevs動態規劃 金明的預算方案
金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間金明自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過 n元錢就行 今天一早,金明就開始做預算了,他把想買的物品分為兩類 主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的...