浙大2012 To Fill or Not to Fill

题意:油箱量为Cmax,每单位油能跑Davg的车,要从杭州跑到距离为D的城市,途中有N个加油站。每个加油站有单位价格Pi和与杭州的距离Di这两个信息。问车最多能跑多远,且在该前提下,最少花费多少钱。

思路:用贪心算法。把自己想成车,要为眼前的利益做出下一步的选择。具体决策见图:

体会:做贪心算法的题,可根据题目给的示例,自己演算一遍,从中总结规律,然后再思考和补充上特例即可。


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

//加油站结构体
struct Station{
	double Pi;                //价格
	double Di;                //距离
};

//相关变量
double Cmax,D,Davg;
double fullD,sumP,nowC;       //fullD:加满油后跑的最大距离,sumP:总油费,nowC:现有油量
int N,i;
Station station[502];

//比较函数
bool Cmp(Station a,Station b){
	if(a.Di<=b.Di)
		return true;
	return false;
}

//求更低价或较低价站函数
//在范围内,有更低价的站,则用z引用带回,返回true,;没有,返回false,用z引用带回
bool FindLowStation(int a,double Dis,int &z);

int main(){
	while(~scanf("%lf %lf %lf %d",&Cmax,&D,&Davg,&N)){     //输入信息
		memset(station,0,502*sizeof(Station));                 //加油站信息清0
		fullD=Cmax*Davg;                                       //计算加满油后跑的最大距离
		for(i=0;i<N;i++)                                       //输入加油站信息
			scanf("%lf %lf",&station[i].Pi,&station[i].Di);
		sort(station,station+N,Cmp);                           //对加油站的距离由小到大排序
		//计算最远距离
		if(station[0].Di!=0){                                  //起始点没加油站
			printf("The maximum travel distance = 0.00\n");
			continue;
		}
		for(sumP=0.0,nowC=0.0,i=0;i<N;){                       //起始点有加油站
		    if(station[i].Di+fullD>=D){                            //fullD内有终点
                if((D-station[i].Di)/Davg<=nowC){                      //油够到终点:直接跑到终点
                    printf("%.2lf\n",sumP);
                    break;
                }
                else{                                                  //油不够到终点
                    int z;
                    if(!FindLowStation(i,(D-station[i].Di),z)){            //剩下的站没有更低价的:加足够油,直达终点
                        if((D-station[i].Di)/Davg<=nowC){                         //油够,直达终点
							printf("%.2lf\n",sumP);
							break;
						}
						else{                                                     //油不够,本站加刚好的油,直达终点
							printf("%.2lf\n",sumP+((D-station[i].Di)/Davg-nowC)*station[i].Pi);
							break;
						}
                    }
                    else{                                                  //剩下的站有更低价的:加足够油,直达z站
                        if((station[z].Di-station[i].Di)/Davg<=nowC){             //油够,直达更低价站
							nowC=nowC-(station[z].Di-station[i].Di)/Davg;
							i=z;
						}
						else{                                                     //油不够,本站加刚好的油,直达更低价站
							sumP+=((station[z].Di-station[i].Di)/Davg-nowC)*station[i].Pi;
							nowC=0.0;
							i=z;
						}
                    }
                }
		    }
		    else{                                                  //fullD内无终点
                if(((i<=N-2)&&(station[i+1].Di-station[i].Di>fullD))||((i==N-1)&&(D-station[i].Di>fullD))){ //fullD内无下一站:不能到终点,能跑多远就多远
                    printf("The maximum travel distance = %.2lf\n",(station[i].Di+fullD));
                    break;
                }
                else{                                                                                       //fullD内有下一站
                    int z;
                    if(!FindLowStation(i,fullD,z)){                                                              //fullD内无更低价:加满油,跑到z
                        sumP+=(Cmax-nowC)*station[i].Pi;
						nowC=Cmax-(station[z].Di-station[i].Di)/Davg;
						i=z;
                    }
                    else{                                                                                        //fullD内有更低价:用足够的油,跑到z
                        if((station[z].Di-station[i].Di)/Davg<=nowC){                                                  //油够
							nowC=nowC-(station[z].Di-station[i].Di)/Davg;
							i=z;
						}
						else{                                                                                          //油不够
							sumP+=((station[z].Di-station[i].Di)/Davg-nowC)*station[i].Pi;
							nowC=0.0;
							i=z;
						}
                    }
                }
		    }
		}
	}
	return 0;
}

//求更低价或较低价站函数
//在范围内,有更低价的站,则用z引用带回最近的,返回true,;没有,返回false,用z引用带回相对最低价的
//a:当前站;Dis:在该距离范围内搜索;z:见上行
bool FindLowStation(int a,double Dis,int &z){
    int j=1;
    double lowerP=station[a+1].Pi;
    while(station[a+j].Di<=(station[a].Di+Dis) && (a+j)<N){
        if(station[a+j].Pi<station[a].Pi){
            z=a+j;
            return true;
        }
        else{
            if(station[a+j].Pi<=lowerP){
                lowerP=station[a+j].Pi;
                z=a+j;
            }
        }
        j++;
    }
    return false;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值