【PAT 1033 To Fill or Not to Fill】

有了高速公路,开车从杭州到任何其他城市都很容易。但是由于汽车的油箱容量有限,我们不得不在路上不时地寻找加油站。不同的加油站可能会给出不同的价格。你被要求仔细设计最便宜的路线。

输入格式:

每个输入文件包含一个测试用例。每一种情况,第一行包含4个正数:Cmax(<=100),水箱的最大容量;D(<=30000)杭州到目的地城市的距离;Davg(<=20),汽车每单位汽油所能行驶的平均距离;以及加油站总数N(<=500)。然后是N行,每行包含一对非负数:Pi,汽油单位价格,Di (<=D),该站到杭州的距离,对于i=1,…,N。一行中的所有数字都用空格隔开。

输出格式:

对于每个测试用例,在一行中打印最便宜的价格,精确到小数点后两位。假设一开始油箱是空的。如果无法到达目的地,打印The maximum travel distance = X,其中X是汽车可以跑的最大距离,精确到小数点后两位。

输入样例:

50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300

输出样例:

749.17
写代码注意点:

1.第一个加油站需要特别判断,如果不在出发点,则必定到不了,因为油箱一开始是空的。

2.判断去哪个加油站的方法是:首先在加满油能到达的距离内,寻找比现在在的加油站便宜的加油站

①存在这样的加油站,则把油加到能够刚好到达这个加油站的量。

②不存在,则把油加满,到达在这些加油站中较便宜的加油站。

3.可以把目的地作为油价为0的加油站。

4.可能出现即使把油加满,在油耗尽前,既到不了任何一个加油站也到不了目的地的情况,此时需要输出能够到达的最大距离。

5.注意每次加油前油箱剩了多少油。

#include<stdio.h>
#include<algorithm>
using namespace std;
struct gas{
	double p;
	double d;
}sta1[505],sta2[505];
bool cmp1(gas a,gas b){/*距离排序*/
    return a.d<b.d;
}
bool cmp2(gas a,gas b){/*油价排序*/
	return a.p<b.p;
}
int main(){
	double Cmax,D,Davg;
	int N;/*大写的都是输入的数字*/
	scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&N);
	for(int i=0;i<N;i++){
		scanf("%lf%lf",&sta1[i].p,&sta1[i].d);
	}
	sta1[N].p=0.0,sta1[N].d=D;/*把目的地作为最后的加油站*/
	sort(sta1,sta1+N,cmp1);
	int n;/*在没有便宜的加油站的情况下,有多少能到达的加油站*/
	int m;/*现在在的加油站*/ 
	int w;/*判断后面有没有便宜的加油站*/ 
	double dmax=Cmax*Davg;;/*加满油走的距离*/ 
	double d1=0.0;/*已经走了的距离*/
	double d2=D;/*剩下要走的距离*/ 
	double cost=0.0;/*花费的钱*/ 
	double c=0.0;/*油箱有多少油*/
	if(sta1[0].d!=0) printf("The maximum travel distance = 0.00");
	/*第一个加油站需要特别判断,如果不在出发点必定失败*/
	else{
		while(d2>0){/*还没到目的地*/
			n=0; 
	        m=0;
	        w=-1;
		    for(int i=0;i<N+1;i++){/*获取在油用完之前能到达的加油站*/
			    if(sta1[i].d==d1) m=i;
			    if((sta1[i].d-d1)<=dmax&&(sta1[i].d>d1)&&sta1[i].p<=sta1[m].p){
				    w=i;/*有便宜的去便宜的*/
				    break;
			    }
			    else if((sta1[i].d-d1)<dmax&&(sta1[i].d>d1)) sta2[n++]=sta1[i];/*没有便宜的去较便宜的*/
			    if((sta1[i].d-d1-dmax)>=0) break;
		    }
		    if(w==-1&&n==0){
			    printf("The maximum travel distance = %.2f",d1+dmax);
			    return 0;
		    }
		    sort(sta2,sta2+n,cmp2);/*在这些加油站中找到最便宜的*/
		    if(w!=-1){/*有便宜的去便宜的*/
		    	if(c*Davg-(sta1[w].d-d1)>=0) c-=(sta1[w].d-d1)/Davg;/*剩了很多油,不要加油*/
		    	else cost+=(sta1[w].d-d1-c*Davg)/Davg*sta1[m].p,  c=0;/*把油加到可以刚好用完/*/
		    	d1=sta1[w].d,  d2=D-sta1[w].d;	
			} 
		    else{/*没有便宜的去较便宜的*/
		    	cost+=(Cmax-c)*sta1[m].p;/*加满油*/ 
		    	c=(Cmax*Davg-(sta2[0].d-d1))/Davg;/*满油减去路上消耗*/
		    	d1=sta2[0].d,  d2=D-sta2[0].d; 
			} 
	    }
        printf("%.2f",cost);
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值