PAT A1033 To Fill or Not to Fill

贪心算法 与1033类似的题貌似在数模优化问题经常碰到
这题理解起来有些费劲

#include<cstdio> //贪心算法 
#include<algorithm>
using namespace std;
const int maxn = 510;
const int INF = 1000000000;

struct station{
	double price,dis;//价格、与起点的距离 
}st[maxn];

bool cmp(station a,station b){
	return a.dis < b.dis; //距离从小到大排 
}

int main(){
	int n;
	double Cmax,D,Davg;
	scanf("%lf%lf%lf%d",&Cmax,&D,&Davg,&n); 
	for(int i=0;i<n;i++){
		scanf("%lf%lf",&st[i].price,&st[i].dis);
	}
	st[n].price = 0;//数组最后面放置终点,价格为0,即"尽可能到" 
	st[n].dis = D;//终点距离为D 
	sort(st,st+n,cmp);//将所有加油站按距离从小到大排序 
	if(st[0].dis != 0) {
		printf("The maximum travel distance = 0.00\n");
	}
	else{
		int now = 0;//当前所处的加油站编号
		//总花费,当前油量,满油行驶距离 
		double ans = 0,nowTank = 0,MAX = Cmax*Davg;
		while(now < n){//每次循环将选出下一个需要到达的加油站 
		// 选出从当前加油站加满油范围内的第一个油价低于当前油价的加油站
		    //如果没有低于当前油价的加油站,那么选择价格最低的那个
			int k = -1;//最低油价加油站的编号
			double priceMin = INF;//最低油价
			for(int i=now+1;i<=n && st[i].dis-st[now].dis <=MAX;i++){
				if(st[i].price < priceMin){//如果该站点油价比当前now站点油价低 
					priceMin = st[i].price;//更新最低油价 
					k = i;
					//如果该更新的最低油价比当前now加油站的油价还低,那么直接中断循环 
					if(priceMin < st[now].price) break;
				}
			}
			if(k ==-1)  break;//!!!如果满油状态下无法找到加油站,那么退出循环输出结果
			 //下面为能找到可到达的加油站k,计算转移花费
			 //need为从now到k需要的油量
			 double need = (st[k].dis-st[now].dis) /Davg;
			 if(priceMin < st[now].price){//如果加油站k的油价低于当前油价
			       //在now加油站只买足够到达加油站k的油
				   if(nowTank < need) { //如果当前油量不足need
				       ans += (need-nowTank) *st[now].price; //只补足need
					   nowTank = 0;//到达加油站k后,油箱内油量变为0
				   }
				   else{
				   	   nowTank -= need;
				   }
			 }
			 else{ //如果加油站k的油价高于当前油价 
			 	ans += (Cmax - nowTank)*st[now].price;//将邮箱加满 
			 	//到达加油站k后邮箱内油量为Cmax - need
				 nowTank =  Cmax - need; 
			 }
			 now = k;//到达加油站k,进入下一层循环  
		}
		if(now == n) {//能到达终点 
			printf("%.2f\n",ans) ;
		}else{//不能到达终点 
			printf("The maximum travel distance = %.2f\n",st[now].dis+MAX);
		}
	}
	return 0; 
}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值