solution Of Pat 1033. To Fill or Not to Fill (25)

48 篇文章 0 订阅

1033. To Fill or Not to Fill (25)

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive numbers: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=20), the average distance per unit gas that the car can run; and N (<= 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: Pi, the unit gas price, and Di (<=D), the distance between this station and Hangzhou, for i=1,…N. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print “The maximum travel distance = X” where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

Sample Input 1:
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
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2
7.10 0
7.00 600
Sample Output 2:
The maximum travel distance = 1200.00


结题思路 :
题意要求我们找到从起点开始到达重点最为廉价的方案。
要求1:如果终点直接就是起点,那么我们的花费为0;
要求2:如果在起点不存在加油站,那么我们将无法到达终点;
要求3:我们加满有最远能行驶a=milesPerUnit*maxCapacity,如果在这个行程内,我们找到的第一个低于加油点价格的下一个加油点,将这个加油点作为下一个加油点。
要点4:在a的行程内,如果没有比现在的加油点更低的加油点,我们在接下来可行的加油点中,选择那个最便宜的加油点,并在当前加油点加满油。
要点5:好吧,其实就是贪心。(不过case有点恶心就是了)

程序步骤:
第一步、在行程以内,判断下一个加油点价格是否低于当前加油点价格,低于:将下一个作为当前点,高于:将下一个点暂存;
第二步、在行程外,从暂存点取最便宜的加油点,由于暂存点中不可能有比当前加油点更便宜的加油点,我们在当前加油点加满油。

具体程序(AC)如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int maxCapcity;//油箱容积
int length;//起点终点的距离
int milesPerUnit;//单位油料能行驶的距离
int n;//总共的加油点个数
struct station
{
  double price;//加油站的单位油价格
  int location;//距离起点的距离
};
int cmp(const station& a,const station& b)
{
  return a.location<b.location;
}
vector<station> stations;//加油站的集合
vector<double> candidate;//暂存行程内的加油站
int chooseMin()//从暂存的加油站集合中选取一个价格最低的加油站
{
  int minIndex=-1;
  double min=60000;
  int index;
  for(int i=0;i<candidate.size();++i)
  {
    index=candidate[i];
    if(stations[index].price<=min)
    {
      min=stations[index].price;
      minIndex=index;
    }
  }
  return minIndex;
}
int main()
{
  cin>>maxCapcity>>length>>milesPerUnit>>n;
  if(n==0)
  {
      cout<<"The maximum travel distance = 0.00"<<endl;
      return 0;
  }
  stations.clear();
  candidate.clear();
  stations.resize(n);
  for(int i=0;i<n;++i)
    cin>>stations[i].price>>stations[i].location;
  sort(stations.begin(),stations.end(),cmp);
  if(length==0)
  {
    cout<<"0.00"<<endl;
    return 0;
  }
  if(stations[n-1].location!=length)
  {
    station tmp;
    tmp.price=0;
    tmp.location=length;
    stations.push_back(tmp);
  }
  else
   stations[n-1].price=0;//attention!case4:终点有加油站,价格较高,这里的处理是因为我的算法需要,可以少几行代码
//被坑的不行
  if(stations[0].location!=0)
  {
    cout<<"The maximum travel distance = 0.00"<<endl;
    return 0;
  }
  //前方特例讨论结束
  int curLocation=0;
  int midLocation=0;
  double cost=0.0;
  int maxDistance=maxCapcity*milesPerUnit;
  int distance=0;
  for(int i=curLocation+1;i<stations.size();++i)
  {
    distance=stations[i].location-stations[curLocation].location;
    if(distance<=maxDistance)//行程范围内
    {
      if(stations[i].price<=stations[curLocation].price)//价格优于当前站
      {
        cost+=stations[curLocation].price*(stations[i].location-stations[curLocation].location);
        curLocation=i;//刚好开到该站即可
        candidate.clear();
      }
      else
        candidate.push_back(i);//价格高于当前站,暂存
    }
    else
    {
      midLocation=chooseMin();
      if(midLocation==-1)//无法到达的情况
      {
        printf("The maximum travel distance = %.2lf\n",stations[curLocation].location+maxDistance+0.0);
        return 0;
      }
      cost+=stations[curLocation].price*(stations[midLocation].location-stations[curLocation].location);
      cost-=(maxDistance-stations[midLocation].location+stations[curLocation].location)*(stations[midLocation].price-stations[curLocation].price);
      //意为在当前点加满油,实际为总价格减去了与下一点的差价×(maxDistance-两个加油站点间的距离)
      curLocation=midLocation;
      i=curLocation;//更新车辆当前的位置
      candidate.clear();
    }
  }
  printf("%.2lf\n",(cost+0.0)/milesPerUnit);
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值