PAT甲组1033.To Fill of Not to Fill思路与注意点--补充《算法笔记》

A1033

题目链接

本题思路

对于我这个新手来讲,在处理这道题的逻辑时,还是费了些周折的,下面来讲一下这道题的具体思路:
很明确这道题是使用贪心法
首先对所有加油站按距离远近进行排序;查找出可行范围内,距离当前加油站最近的,油价比当前低的加油站,加一部分油,使其刚好加到更合适的加油站。
若可行范围内没有比现在更便宜的加油站,则说明此处是相对最便宜的,应该把油加满,然后前往接下来价格相对较低的加油站。
若可行范围内没有可以到达的加油站,则本次旅行不能到达终点,算出最大距离即可

个人解题时的思路与启示

个人一开始未做出的原因:题意理解不到位逻辑处理的先后顺序不清晰细节分析的不够透彻。这个博客也是帮助我总结一下自己在做题过程中的思路变化。

个人思路

一开始对这道题题意的理解并不够深刻,意识到并不一定非要一次性加满,可以加到合适位置;但按这个思路走下去又忘记了,遇到比较便宜的加油站,当然是需要加满油的!其次过程中,不知道应该先加油还是先判断,从当前位置遍历还是从当前位置的下一位置遍历(做着做着就把自己绕里头了);一些细节处理(当时的思路与想法):可行范围内只有一站,不加油无法抵达终点,则不得不在此站加油;终点的判断,何时选择一次性把油加到终点位置;还尚未考虑未到达的情况如何处理

很明显当时思路特别乱,不知道应该先处理哪个,导致忽然有一个想法冒出来,要改动很多的代码

启示

要在做题前把思路捋清楚!最好的方法就是,根据提供的样例,明白得出这个结果的原因,随后再考虑一些边界问题和细节处理问题

几点注意与技巧

1、将终点转换为最后一个加油站(价钱为0,距离为终点的距离)会方便很多的判断
2、如果需要表示三种状态时,用整型变量(0,1,2),需要表示两种,则用bool类型即可。本题中的isLower即是采用这种思想,来表示中途加油站且价格更便宜,中途有加油站但价格更贵,中间无加油站这三种状态

代码

#include 
using namespace std;
const double INF = 0x3fffffff;
double C, D, DA;
//总花费,当前油量,当前位置,当前价格,满油最大行驶距离,本次最大旅行距离
double cost, nowCapa, hereDist, herePrice, maxEachDist, maxTravelDist, betwDist;
int N;
struct stations{
	double price;
	double dist;
}sta[505];
bool cmp(stations s1, stations s2)
{
	return s1.dist < s2.dist;
}
int main(int argc, char *argv[]) {
	scanf("%lf%lf%lf%d", &C, &D, &DA, &N);
	for(int i = 0; i < N; i++)
	{
		scanf("%lf%lf", &sta[i].price, &sta[i].dist);
	}
	//对终点的处理 
	sta[N].dist = D;
	sta[N].price = 0.00;
	sort(sta, sta + N, cmp);
	maxEachDist = C * DA;
	bool cmplt = true;//标记最后是否能到达终点 
	if(sta[0].dist != 0)//无法出发 
	{
		cmplt = false;
		maxTravelDist = 0; 
	}
	else//可出发 
	{	
		int nextIndex, lastIndex, beforeIndex;//记录下一站下标和可行范围内最后一站的下标以及当前正在加油的那一站下标 
		for(int i = 0; i < N; i++)
		{
			if(i == 0)
			{
				herePrice = sta[i].price;
				hereDist = sta[i].dist;
				beforeIndex = i;
			}
			else if(i == nextIndex)
			{
				herePrice = sta[i].price;
				hereDist = sta[i].dist;
				nowCapa -= (hereDist - sta[beforeIndex].dist) / DA;
				beforeIndex = i;
			}
			else
			{
				continue;
			}
			//0:没有合适的加油站且中间也无法加油 1:中间可加油但油价并不低 2:中间有油价更低的 
			int isLower = 0;//标记是否存在比现在低的油价
			//遍历之后是否存在价钱更低的 
			for(int j = i + 1; j <= N; j++)
			{
				if(sta[j].dist <= hereDist + maxEachDist)
				{
					if(sta[j].price < herePrice)
					{
						betwDist = sta[j].dist - hereDist;
						//判断当前油量是否能到达 
						double need = (betwDist - nowCapa * DA) / DA;
						if(need > 0)//不够到达需要加油 
						{
							nowCapa += need;
							cost += need * sta[i].price;
						}
						nextIndex = j;
						isLower = 2;
						break;
					}
					else
					{
						isLower = 1;
						lastIndex = j;
					}
				}
				else
				{
					if(isLower == 1)
					{
						double tempPrice = INF;
						for(int k = i + 1; k <= lastIndex; k++)//寻找价格相对较低的 
						{
							if(sta[k].price < tempPrice)
							{
								nextIndex = k;
								tempPrice = sta[k].price;
							}
						}
						cost += (50 - nowCapa) * sta[i].price;
						nowCapa += 50 - nowCapa;
						break;
					}
					else if(isLower == 0)
					{
						cmplt = false;
						maxTravelDist = hereDist + maxEachDist;
						break;
					}
				}	
			}
			if(!cmplt)
			{
				break;
			}
		}
	}
	if(!cmplt)//到达不了终点 
	{
		printf("The maximum travel distance = %.2f", maxTravelDist);
	}
	else
	{
		printf("%.2f", cost);
	}
	return 0;
}

你可能感兴趣的:(PAT)