可能有人说这是一题贪心水题,但是我却觉得虽然思路明白,但其代码实际上并不好写。
假设在某一站时,该站为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;
}