pat甲級 1033 To Fill or Not to Fill (25 分) (思維 貪心)

題目鏈接:傳送門

思路:本來想dp,然後得了11分,因爲沒有考慮在前一個加油站可以加滿油的情況。 下來說貪心解法:首先每個位置取最小的油價保存,然後在計算時分兩種情況,設當前位置爲t。
(1)前方有價格更低的加油站p,直接選取這個加油站p,然後記錄走到這個加油站要花費的錢.
(2)前方沒有價格更低的加油站,爲了到達需要選取一個價格相對最小的站p1,這裏可以先在當前加油站t加滿油,再去目標加油站p1,所以算的時候直接算上加滿油的油錢,然後記錄一個免費距離ol,在下一個加油站p1可以用。(在下一個加油站p1計算時的時候直接減掉這段距離即可,不會減成負的 , 可以證明)

代碼:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 3e4 + 5 , INF = 0x7f7f7f7f;
double g[maxn];
vector <int> v;

int main() {
	int c , d , da , n;
	cin >> c >> d >> da >> n;
	for(int i = 0 ; i <= d ; i++)g[i] = INF;
	for(int i = 0 ; i < n ; i++) {
		double p;
		int dst;
		cin >> p >> dst;
		if(g[dst] == INF)v.push_back(dst);
		if(g[dst] > p)g[dst] = p;
	}
	g[d] = 0; v.push_back(d);
	sort(v.begin() , v.end());
	int cnt = 0;
	double ans = 0;
	double ol = 0;
	if(v[0] > 0) {
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	//cout << "size = " << v.size() << "\n";
	for(int i = 0 ; i < v.size() - 1 ; ) {
		int t = i;
		int x = -1;
		i++;
		double mm = INF;
		while(i < v.size() && v[i] - v[t] <= c * da) {
			if(g[v[i]] < mm) {
				x = i;
				mm = g[v[i]];
				if(mm < g[v[t]])break;
			}
			i++;
		}
		if(x != -1) {
			if(mm > g[v[t]]) {
				ans += (double)(c - ol / da) * g[v[t]];
				ol = c * da - (v[x] - v[t]);
			}
			else {
				ans += (double)(v[x] - v[t] - ol) / da * g[v[t]];	
				ol = 0;	
			}
			cnt = v[x];
			i = x;	
		}
		else {
			cnt = v[t] + c * da;
			printf("The maximum travel distance = %.2f\n" , (double)cnt);
			return 0;	
		}
	}
	printf("%.2f\n" , ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章