PAT (Advanced Level) 1033 To Fill or Not to Fill (25分)【贪心】

PAT (Advanced Level) 1033 To Fill or Not to Fill (25分)【贪心】

题意:给你油箱容量 C C C,给你最远想要到达的距离 D D D,给你汽车每升油所能支持的距离 D a v g D_{avg} Davg,给你加油站的数量 N N N
然后每个加油站,给你距离起点的位置以及油价。
问,你最少可以花费多少美元到达终点。

分析:作为老 D P DP DP 恐慌性选手,起手就是一顿动态规划,然而最后复杂度在 30000 ∗ 500 ∗ 500 30000 * 500* 500 30000500500 最后一个测试点最直接 T L E TLE TLE.

本题可通过贪心的思想来实现,我需要维护当前油箱里的剩余油量。

  • 假设我已经抵达一个加油站,如果我的装满油箱足以支撑我到达下一个油价更便宜的加油站:
    1 要么我油箱里的油足够,我就选择不在当前加油站加油;跳到离我当前位置最近的油价比当前加油站油价低的加油站
    2 要么我油箱里的油不够,我就恰好加到可以抵达下一个拥有更便宜油价的加油站。跳到目的加油站

  • 假设我抵达了一个加油站,在当前加油站到我装满油箱所能到达的距离的区间之内,没有更便宜的加油站:
    1 我加满油可以抵达终点,直接加油加到恰好可以抵达终点,跳到终点
    2 加满油并不能抵达终点,直接把油加满,然后跳到剩下区间内油价最便宜的那个加油站

WA点

  • 注意,你选取的下一个加油站不是下一个区间里油价最低的,而是离你最近的油价比你低的。建议先手算一遍第一个样例。
  • 注意,如果起点没有加油站,最远距离直接输出为 0.00 0.00 0.00
  • 使用 d o u b l e double double

贪心AC代码:

#include<iostream>
#include<cstring> //memset
#include<string>
#include<cstdio> //scanf
#include<string>
#include<utility> // pair
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<functional> //less greater 
using namespace std;
//MSMYS
// the same node may be at different position(address).
#define LL long long int
#define ll LL
#define INF 0x3f3f3f3f
const double eps = 1e-8;
const double TINF = 1e10;
const int maxn = 5e2 + 10;
const int maxm = 3e4 + 10;
double dp[maxm];
double money[maxm];
struct Gas_Station {
	int id;
	int pos;
	double price;
}a[maxn];
int C, D, Davi, N;
int cmp(Gas_Station A, Gas_Station B) {
	if (A.pos == B.pos) return A.price < B.price;
	return A.pos < B.pos;
}
int main() {
	scanf("%d %d %d %d", &C, &D, &Davi, &N);
	for (int i = 0; i < maxm; i++) {
		money[i] = TINF;//没有加油站
	}
	for (int i = 1; i <= N; i++) {
		double pri; int distance;
		scanf("%lf %d", &pri, &distance);
		a[i].price = pri;
		a[i].pos = distance;
		money[distance] = min(pri, money[distance]);
	}
	money[D] = 0;
	int MaxDAC = C * Davi;
	sort(a + 1, a + 1 + N, cmp);
	double res = 0.0; // the capacity of gas tank
	double cost = 0.0; // the cost of gas nw
	//double length = 0; // the length of the gas in tank can be successive.
	int dis = 0;
	if (a[1].pos > 0) {
		puts("The maximum travel distance = 0.00");
		return 0;
	}
	int k = 0;
	//多出来三公里的钱!
	while (dis <= D) {
		double Price = money[dis];
		double length = res * Davi; // 当前油箱内剩余油所可以支持的距离
		double MinPrice = TINF - 10; int index = -1; int flag = 0;
		for (int i = dis + 1; i <= dis + MaxDAC && i <= D; i++) {
			if (money[i] < MinPrice && i != D) {
				flag = 1;
				index = i;
				MinPrice = money[i];
			}
			if (MinPrice <= Price) {
				break;
			}
			if (i == D) {
				if (!flag) {
					index = D;
					MinPrice = 0;
				}
			}
		}

		if (index != -1 && MinPrice <= Price) {
			if (dis + length >= index) { // 直接跑过去,当前加油站不用加油
				res = res - (index - dis) / Davi;
				dis = index;
			}
			else { // 刚刚好加油加到下一个加油站
				cost += 1.0 * (index - dis - length) / Davi * Price;
				res = 0;
				dis = index;
			}
		}
		else {
			if (index == -1) {
				if (dis + MaxDAC <= D) {
					dis = dis + MaxDAC;
					cost += 1.0*(C - res) * Price;
					res = 0;
				}
				else {
					cost += 1.0*(D - dis - length) / Davi * Price;
					res = 0;
					dis = D;
				}

				break;
			}
			else {
				if (dis + MaxDAC >= D) {
					cost += 1.0*(D - dis - length) / Davi * Price;
					res = 0;
					dis = D;
				}
				else {
					cost += 1.0*(C - res)*Price;
					res = C - 1.0*(index - dis) / Davi;
					dis = index;
				}
			}
		}
		//printf("%.2f\n", cost);
	}
	if(dis == D)
		printf("%.2f\n", cost);
	else printf("The maximum travel distance = %.2f\n", 1.0 * dis);

	return 0;
}

DP TLE 代码:回来再琢磨琢磨能不能优化

#include<iostream>
#include<cstring> //memset
#include<string>
#include<cstdio> //scanf
#include<string>
#include<utility> // pair
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<functional> //less greater 
using namespace std;
//MSMYS
// the same node may be at different position(address).
#define LL long long int
#define ll LL
#define INF 0x3f3f3f3f
const double eps = 1e-8;
const double TINF = 1e10;
const int maxn = 5e2 + 10;
const int maxm = 3e4 + 10;
double dp[maxm];
struct Gas_Station {
	int id;
	int pos;
	double price;
}a[maxn];
int C, D, Davi, N;
int cmp(Gas_Station A, Gas_Station B) {
	if (A.pos == B.pos) return A.price < B.price;
	return A.pos < B.pos;
}
int main() {
	scanf("%d %d %d %d", &C, &D, &Davi, &N);
	for (int i = 1; i <= N; i++) {
		double pri; int distance;
		scanf("%lf %d", &pri, &distance);
		a[i].price = pri;
		a[i].pos = distance;
	}
	for (int i = 0; i <= D; i++) {
		dp[i] = TINF;
	}
	dp[0] = 0.0;
	int MaxDAC = C * Davi;
	//cout << MaxDAC << endl;
	sort(a + 1, a + 1 + N, cmp);
	int pre_distince = 0;
	for (int i = 1; i <= N; i++) {
		int Pos = a[i].pos;
		//只考虑这个加油站可能影响的距离
		for (int j = Pos; j <= Pos + MaxDAC; j++) {
			for (int k = Pos; k <= j; k++) {
				double tmp = dp[k] + 1.0 * (j - k) / Davi * a[i].price;
				dp[j] = min(tmp, dp[j]);
			}
		}
	}
	if (dp[D] > TINF - 10.0) {
		for (int i = 0; i <= D; i++) {
			if (dp[i + 1] > TINF - 10.0) {
				printf("The maximum travel distance = %.2f\n", 1.0*i);
				return 0;
			}
		}
	}
	printf("%.2f\n", dp[D]);
	/*for (int i = 1; i <= 10; i++) {
		printf("%.2f\n", dp[i]);
	}
*/
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值