旅行家的預算(貪心算法)

問題描述
  一個旅行家想駕駛汽車以最少的費用從一個城市到另一個城市(假設出發時油箱是空的)。給定兩個城市之間的距離D1、汽車油箱的容量C(以升爲單位)、每升汽油能行駛的距離D2、出發點每升汽油價格P和沿途油站數N(N可以爲零),油站i離出發點的距離Di、每升汽油價格Pi(i=1,2,……N)。計算結果四捨五入至小數點後兩位。如果無法到達目的地,則輸出“No Solution”。
輸入格式
  第一行爲4個實數D1、C、D2、P與一個非負整數N;
  接下來N行,每行兩個實數Di、Pi。
輸出格式
  如果可以到達目的地,輸出一個實數(四捨五入至小數點後兩位),表示最小費用;否則輸出“No Solution”(不含引號)。
樣例輸入
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
樣例輸出

26.95


思路:是找在最大行駛距離內尋找比當前便宜的加油站,然後判斷是否能一次到達,不能的話先加滿,然後一個一個判斷直到剩下的油量不足到下一個加油站就加油,加適量。

於是有以下2 situations:

1.這個站點j 就是pos 
  再細分兩種情況:
    1.從pos就可以走到終點
      於是我們把油加到剛好到達終點即可
         cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];就得到了最後答案。
          remain是當前剩餘的油
    2.從pos不能一把走到終點
      於是,從當前位置走,走到哪裏加油都不夠在pos這裏加油划算。
      所以加滿。
2.這個站點j 是在pos後面的某個站點
  也有兩種情況
    1.當前剩餘的油remain不夠走到j
      於是我們,把油加來剛好能夠走到j就行了。(因爲j這裏好好便宜!)
    2.剩餘的油remain足夠,直接開過去就行了。
########具體操作見如下代碼

#include<iostream>  
#include<algorithm>  
#include<iomanip>  
using namespace std;
double d[10000], p[10000];   //出發點每升汽油的價格p
int main()
{
	ios::sync_with_stdio(false);  //取消cin在stdin上的同步,增加cin的讀取效率
	double d1, c, d2;  
	int n;   //沿途油站數目
	cin >> d1 >> c >> d2 >> p[0] >> n;
	d[n + 1] = d1;   //第n個油站後即爲最後的站點
	for (int i = 1; i <= n; i++)  //輸入每一個油站離出發點的距離以及每個站點汽油的價格
	{
		cin >> d[i] >> p[i];
	}
	int pos = 0;
	double remain = 0, cost = 0;
	do
	{
		bool found = false;   //判定能不能到達
		for (int i = pos + 1; i <= n + 1 && d[i] <= d[pos] + c*d2; i++) //循環判斷加滿油能不能到達下一個加油站
		{
			if (p[i] < p[pos])   //判斷下個站點汽油的價格是不是比這個pos站點汽油的價格小
			{
				if (d[pos] + remain*d2 >= d[i])  //若是剩餘的油足夠,剛好開過去
				{
					remain -= (d[i] - d[pos]) / d2;    //剩餘的油減少,減少量就是從一個站點到下一個站點用到的油
				}
				else  //剩餘的油不夠
				{
					cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];  //還需要加的油花費的價錢,不用加滿
					remain = 0;   //到達下一個站點恰好沒油了,所以剩餘汽油量清0
				}
				pos = i;
				found = true;
				break;
			}
		}
		if (!found)
		{
			cost += (c - remain)*p[pos];  //不能到達前花費了多少錢
			remain = c - (d[pos + 1] - d[pos]) / d2;     //還剩多少油
			if (remain >= 0) pos++;  //小於0,油根本不夠到達下一個站點,大於0,代表可以去下一個加油站
			else
			{
				cout << "No Solution";
				return 0;
			}
		}
	} while (pos <= n);  //循環條件:沒到達終點
	cout.setf(ios::fixed);  //以定點形式顯示浮點數
	cout << setprecision(2) << cost;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章