旅行家的预算(贪心法~~)

在这里插入图片描述
        可能有人说这是一题贪心水题,但是我却觉得虽然思路明白,但其代码实际上并不好写。
        假设在某一站时,该站为Pos,我们看,向后探测看能否找到油价比它便宜且最便宜的油价,这时分为两种情况:
        1.该站油价就是最便宜的,这时根据能否到终点又需分两种情况
        1.能到终点,则刚好加到至终点的油即可,cost = ((d[i] - d[pos])/d2-remain)*p.[pos];
        2.不能到终点,则加满即可
        1.在其能够到达区域有更便宜的油,这时能否根据剩余的油能够到达后面的j站点分为两种情况
        1.剩余的油不够到达后面一站点j,这时只需加满到刚好到j站点的油即可
        2.剩余的油够达到后一站点j时直接开过去即可
代码分析:

	cin>>d1>>c>>d2>>p[0]>>n;
	d[n+1] = d1;
	for(i = 1; i <= n; i++)
	{
		cin>>d[i]>>p[i];	
	}
	int pos = 0;//初始站点从0开始 
	double remain = 0, cost;//remain表示为油箱中所剩余的油量

        预备阶段,需要说明的是这里的remain十分重要,记录剩余的油量,因为每次向前出发都是需要根据剩余的油量进行判断。

		for(i = pos+1; i <= n+1&&d[i] <= d[pos]+c*d2; i++)//加满油是否能够到达下一个加油站点 
		{
			if(p[i] < p[pos])
			{
				if(d[pos] + remain*d2 >= d[i])
				{
					remain -= (d[i]-d[pos])/d2;//油量够 
				}
				else
				{
					cost += ((d[i]-d[pos])/d2-remain)*p[pos];//油量不够 
					remain = 0; 
				}
				pos = i; found = true; break;
			}
		}

        核心代码,向前进行探测时,i 从当前下一站点出发,而且的d[i] <= d[pos]+c*d2可以理解为满油状态下所能到达的最远站点,之后再比油价,油价更低,则判断当前剩余油能否跑到后面站点即if、else语句执行该功能。

if(!found)
		{
			cost += (c-remain)*p[pos];
			remain = c-(d[pos+1]-d[pos])/d2;
			if(remain >= 0) pos++;
			else
			{
				printf("No Solution");
				return 0;	
			} 
		}

        如果当前站点的油价即为最小,我们需要走到下一站点,但是既然这一站点的油价最小,此时应加满油再来判断能否到达下一站点。
完整代码:

#include<iostream>
using namespace std;
double d[10000], p[10000];
int main()
{
	double d1, c, d2;
	int i, n;
	cin>>d1>>c>>d2>>p[0]>>n;
	d[n+1] = d1;
	for(i = 1; i <= n; i++)
	{
		cin>>d[i]>>p[i];	
	}
	int pos = 0;//初始站点从0开始 
	double remain = 0, cost;//remain表示为油箱中所剩余的油量 
	do
	{
		bool found = false;
		for(i = pos+1; i <= n+1&&d[i] <= d[pos]+c*d2; i++)//加满油是否能够到达下一个加油站点 
		{
			if(p[i] < p[pos])
			{
				if(d[pos] + remain*d2 >= d[i])
				{
					remain -= (d[i]-d[pos])/d2;//油量够 
				}
				else
				{
					cost += ((d[i]-d[pos])/d2-remain)*p[pos];//油量不够 
					remain = 0; 
				}
				pos = i; found = true; break;
			}
		}
		//不能达到时,found仍为false 
		if(!found)
		{
			cost += (c-remain)*p[pos];
			remain = c-(d[pos+1]-d[pos])/d2;
			if(remain >= 0) pos++;
			else
			{
				printf("No Solution");
				return 0;	
			} 
		}
	}while(pos <= n); 
	printf("%.2f", cost);
	return 0;	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值