NOIP1999提高组 旅行家的预算

4 篇文章 0 订阅

NOIP1999提高组 旅行家的预算

题目描述

    一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出格式

    输入格式:

    第一行,D1,C,D2,P,N。
    接下来有N行。
    第i+1行,两个数字,油站i离出发点的距离Di和每升汽油价格Pi。

    输出格式:

    所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。

输入输出样例

    输入样例:

    275.6 11.9 27.4 2.8 2
    102.0 2.9
    220.0 2.2

    输出样例:

    26.95

说明

    N≤6,其余数字≤500

解题分析:

    采用贪心算法
    从某一点(假设为k加油站,开始为起点)出发,计算从该点出发加满油所能走到的最远距离。包括以下几种情况:
    1、所达到的距离内,有加油站的油价比加油站k的油价低(假设第一个为x加油站),则在k加油站加适量的油,开到x油站时正好油用完,并以x加油站为起点继续判断。此时邮箱没有余油。
    2、所达到的距离内,没有加油站的油价比加油站k的油价低(假设这些油站中x油站的油价最低),则在k加油站加满油,开到x加油站时以x为起点继续判断。此时邮箱有部分余油,在计算从x加油站所加的油量时要减去该余油数。如果此时能到达终点,则从x加油站加适量的油能够开到终点即可。
    3、如果在某个油站加满油不能跑到下一油站,则输出“No Solution”。

    在实现时,将起点和终点都加入到加油站数组,其中起点的距离为0,终点的距离为D1, 油价为一个较大值,比如1000

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           using namespace std; int main(){ ios::sync_with_stdio(false); double d1, c, d2, p, p1, dis, ans = 0.0, min, rem; double sta[8][2]; int n, i, start, flag, min_i; cin>>d1>>c>>d2>>p>>n; sta[0][0] = 0; sta[0][1] = p; for(i=1; i<=n; i++) cin>>sta[i][0]>>sta[i][1]; sta[++n][0] = d1; sta[n][1] = 1000; dis = c * d2; // 从起点出发最多能走的距离 start = 1; // 起点的油站编号 rem = 0; // 到达该起点时,邮箱剩余油量 p1 = p; // 起点油价 while(1){ flag = 0; min = 1000; for(i=start; i<=n; i++){ if(min > sta[i][1]){ min = sta[i][1]; min_i = i; } // 从出发点开始,能够到达比它油价低的加油点 if(sta[i][0] <= dis && sta[i][1] <= p1){ ans += ((sta[i][0] - sta[start-1][0]) / d2 - rem) * sta[start-1][1]; start = i+1; dis = sta[i][0] + c * d2; // 加满有所能跑的最长距离 p1 = sta[i][1]; rem = 0; // 到该油站时,正好将油用完 flag = 1; break; } if(sta[i][0]>dis){ //没有油价比起点更低的加油站 flag = 2; break; } } if(flag == 2){ ans += sta[start-1][1] * (c - rem); // 在上一个起点处,将邮箱加满 // 从加油站min_i继续出发,注意此时邮箱有余油 rem = c - (sta[min_i][0] - sta[start-1][0]) / d2; start = min_i+1; dis = sta[min_i][0]; p1 = sta[min_i][1]; flag = 0; } else if(!flag){ // 已经走到终点或出现不能逾越的距离 if(i==start && sta[i][0] - sta[i-1][0] > c * d2){ cout<<"No Solution"< 
          
            c*d2){ cout<<"No Solution"< 
            
           
          
         
       
      
      
     
     
    
    
   
   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值