To Fill or Not to Fill

问题 C: To Fill or Not to Fill
时间限制: 1 Sec 内存限制: 32 MB
提交: 904 解决: 186
[提交][状态][讨论版][命题人:外部导入]
题目描述
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.

输入
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.

输出
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.

样例输入
59 525 19 2
3.00 314
3.00 0
样例输出
82.89

本题是一个非常不错的贪心习题,个人觉得有些难度。废话不多说,先来看看思路:
不妨设当前所在加油站编号为now ,这里最重要的是如何选择下一个加油站,从而使得cost最小

我们先将加油站按照距离起点的距离从小到大排序
1、if(gas[0].d!=0) 那么汽车连启动都成问题 输出最大行驶距离为0.00
2、选出从当前加油站位置在油满状态下能到达范围内第一个低于当前油价的加油站,
如果没有低于当前油价的,则选择油价最低的那个加油站。
a、存在低于当前油价的加油站k:我们只要加足够到达k的油即可
b、不存在低于当前油价的加油站k:在now位置将油箱加满
3、一旦now=num 就说明到达了终点,否则最大行驶距离为gas[now].d+MAX

Notes: 在终点设置一个加油站 且油价为0,因为有了它就不用记录当前行驶的距离
当加油站编号为num 时就可以直接确定已经到达终点。
以下是AC代码:

#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<ctime>
#include<algorithm>
#include<iterator>
#include<vector>
#include<stack>
#include<set>
#include<queue>
#include<map>
#include<utility>
using namespace std;
const int N=501;
const int INF=0x3f;
struct node{
    double price;
    double d;

    bool operator <(node n1) const{
      return d<n1.d;    //按距离从小到大排序
    }
}gas[N];
double C_tank,max_distance,avg;
int num;
int main()
{
	ios::sync_with_stdio(false);
    while(cin>>C_tank>>max_distance>>avg>>num){
        for(int i=0;i<num;i++){
            cin>>gas[i].price>>gas[i].d;
        }
        //在终点设置一个加油站 且油价为0
        gas[num].d=max_distance;
        gas[num].price=0;   //有了它就不用记录当前行驶的距离
        sort(gas,gas+num);
        
        if(gas[0].d){
            cout<<"The maximum travel distance = 0.00"<<endl;
        }else{
            int MAX=C_tank*avg; //油满状态下能走的最远距离
            int now=0;  //当前加油站编号
            double cost=0;//油费
            double nowtank=0;  //当前油量
            while(now<num){//每次循环将选出下一个加油站的编号

            //选出从当前加油站位置在油满状态下能到达范围内第一个低于当前油价的加油站
            //如果没有低于当前油价的,则选择油价最低的那个
                int k=-1;   //最低油价的加油站编号
                int pricemin=INF;   //从Now往后的最低油价
                for(int i=now+1;i<=num && gas[i].d-gas[now].d<=MAX;i++){
                    if(gas[i].price<pricemin){
                        pricemin=gas[i].price;
                        k=i;
                    }
                    //如果找到第一个低于当前油价的加油站则退出
                    if(pricemin<gas[now].price){
                        break;
                    }
                }

                if(k==-1) break;    //油满状态下无法找到任何一个加油站,直接退出
                //以下计算能找到下一个加油站情况 下的花费
                //need 为Now到下一个加油站k 需要的油量
                double need=(gas[k].d-gas[now].d)/avg;
                if(gas[k].price<gas[now].price){//如果下一个加油站油价低于当前油价
                //只购买需要的油价
                    if(nowtank<need){
                        cost+=(need-nowtank)*gas[now].price;//补足need
                        nowtank=0;//到达下一加油站时油箱内耗尽
                    }else{
                        //先用油箱里的油,不加油
                        nowtank-=need;
                    }
                }else{//如果下一个加油站油价高于当前油价
                    //将当前油箱加满
                    cost+=(C_tank-nowtank)*gas[now].price;
                    nowtank=C_tank-need;   //到达k后,更新当前油量 
                }
                now=k;  //到达加油站K 进行下一层循环
            }

            if(now==num){
                printf("%.2lf\n",cost);
            }else{
                printf("The maximum travel distance = %.2lf\n",gas[now].d+MAX);
            }
        }
    }
    system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值