PAT 1033. To Fill or Not to Fill (25) 贪心算法+特殊情况判断

/*************************
题意:
加油站贪心问题
给出公路上各个加油站的位置,以及各站油的价格。
问如果车子要开D的距离,则最少需要花多少钱?
如果过程中油会不够,到达不了终点,则给出最远能开多远
/************************
求解思路和注意点:
贪心思想。
油箱容量cmax * 每升油可行驶距离davg  = 车子满油情况下能行驶的最远距离max_dis
当车子到达某个站点now_s时,判断一下接下来在max_dis的范围内
	是否有1个比now_s站点便宜的站点great_s(选最近的那个)
	如果是
		装上适当的油,使得开到great_s时,油刚好用完(为了接下来尽可能多地装great_s的便宜油)
	如果范围内没有比now_s便宜的站点
		则选择范围内最便宜的一个站点min_s
		车子先在now_s装满油,再开到那个站点(为了接下来尽可能少地装min_s的贵油)。
如果发现范围内找不到站点,距离又不够,则说明到达不了,把油装满开完为止。

注意点(坑点):
	1.可能会有距离相同,价格不同的站点,即同一位置有2个站点。
	2.距离也可能是浮点数。
	3.★起点处可能没有站点,这样的话是开不了车的,距离最长为0。
	4.中间计算用double,最后保留2位小数即可。
************************/

/***********************
笔记:
1.写好一段关键代码后,先关注一下是否初始化完全。
2.初始处是否可能存在为空的情况。
3.审题时,关注一下数字的类型,是否可能为浮点数
		  关注一下输入是否是different,还是可能same。
*********************/
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<stack>
using namespace std;
#define M 100001
#define INF 0x7fffffff
struct station{
	double price;
	double dis;
};

bool cmp(station a,station b){
	if(a.dis<b.dis)
		return true;
	else if(a.dis == b.dis)
		return a.price < b.price;
	else return false;
}
int main(){
	int cmax,davg,n,dmax;
	scanf("%d%d%d%d",&cmax,&dmax,&davg,&n);
	double p;
	double d;
	vector<station> vsta;
	station s;
	while(n--){
		scanf("%lf%lf",&p,&d);
		s.price=p;
		s.dis=d;
		vsta.push_back(s);
	}
	//终点也入,并把价格认为是0
	s.dis = dmax;
	s.price = 0;
	vsta.push_back(s);
	sort(vsta.begin(),vsta.end(),cmp);
	
	int i,nowi=0,mini=0,selecti=0;
	double cost=0,nowc=0,nowlen=0;
	station mins,nows,selects;
	nows = vsta[0];

	//起点处如果没有加油站,则寸步难行!!!!!
	if(nows.dis != 0){
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	nowi = 0;
	while(vsta[selecti].dis != dmax){
		mini = -1;
		mins.price = INF;
		for(i = nowi + 1; i < vsta.size(); i++){
			//说明最大距离内没找到比它价格低的站点
			//则选一个区间内价格最低的,把自己买满了再过去
			if(vsta[i].dis - nows.dis > cmax*davg){
				selecti = mini;
				//如果范围内找不到一个站点,则返回最大距离。
				if(selecti == -1){
					nowlen = nows.dis + cmax*davg;
					printf("The maximum travel distance = %.2lf\n",nowlen);
					return 0;
				}
				cost += (cmax - nowc) * nows.price;
				nowc = cmax - double(mins.dis - nows.dis)/double(davg);
				break;
			}
			//找到比它价格低的,直接退出,用这个节点
			if(vsta[i].price <= nows.price){
				selecti = i;
				//若接下来的路程需要补充汽油,则补充到正好用完就行、
				cost += (double(vsta[i].dis - nows.dis)/double(davg) - nowc)*nows.price; 
				nowc = 0;
				break;
			}
			//这里维持寻找一个区间内价格最低站点
			else if(vsta[i].price < mins.price){
				mini = i;
				mins = vsta[i];
			}
		}
		nowi = selecti;
		nows = vsta[selecti];
	}
	printf("%.2lf\n",cost);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值