ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

旅行家的预算(单调队列)

2021-02-06 06:32:24  阅读:219  来源: 互联网

标签:oil 队列 back int ans front now 旅行家 单调


原题:

旅行家的预算

时间限制: 1 Sec  内存限制: 125 MB

题目描述

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站ii离出发点的距离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

   
  题意:

  距离为d1的两个地点之间有n个......算了题目说的很清楚了。

  变量含义:

  这道题字母比较多,首先把题中的字母的含义搞清楚,

  D1:两地之间距离

  D2:每升油可以行驶的路程

  D[i] ( 1≤i≤n ) :第i个加油站到起点的距离

  C:油箱容量

  n:加油站数量

  P[i] ( 0≤i≤n ) :第i个加油站每升油的价钱(包括起点)

 

  这道题在洛谷中的标签是『贪心』『递归』,但是我打算用单调队列做。

  先说一下整体的思路:可以现在读入的时候处理一下无解的情况,即就算油箱装满也跑不完全程,有这种情况的直接输出“No Solution”

  因为不知道要买多少油,不妨假设油可以买进后任意时点地点转卖出。在起点先把油箱装满油,出发到下一个点(当然在路上花掉了一些油),我们假设我们可以控制花掉了哪些油——路上先花掉便宜的油,到达目的地后将比该地贵的油转卖出,最后装满该地的油。这里维护一个单调队列,使油的价钱单调上升,使用队头便宜的油,转卖队尾贵的油(注释在代码中)。

代码来啦——

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<queue>
 4 using namespace std;
 5 const int N=505;
 6 double c,d1,d2,oil,ans,d[N],p[N];  //c,d1,d2,d[],p[]如题意,oil指现有油量,ans即花费的钱
 7 struct node{ double cost,v; }now;  //队列储存结构体,包含买来的每种油的价钱(cost)和体积(v)
 8 int n;
 9 deque<node> q;  //STL双端队列
10 int main()
11 {
12     scanf("%lf %lf %lf %lf %d",&d1,&c,&d2,&p[0],&n);
13     //两市之间的距离d1,油箱容量c,每升油能行驶的距离d214     //起点油价p[0],加油站数量n
15     d[n+1]=d1;  //把终点看成是第n+1个加油站
16     for(int i=1;i<=n;i++)  scanf("%lf %lf",&d[i],&p[i]);
17     for(int i=2;i<=n+1;i++)
18         if(d[i]-d[i-1]>c*d2){ printf("No Solution"); return 0; }  //如果油箱装满也跑不完说明没有解
19     ans=p[0]*c,oil=c;
20     q.push_back({p[0],c});  //起点加入所有油
21     for(int i=1;i<=n+1;i++)
22     {
23         double dis=d[i]-d[i-1],need=dis/d2;  //need指需要几升油
24         while(!q.empty() && need>0)
25         {
26             now=q.front(); q.pop_front();  //取出已购买的油中最便宜的油
27             if(now.v>need)
28             {
29                 oil-=need,now.v-=need;
30                 q.push_front(now);  //如果油够多把多余的油放回去
31                 break;
32             }
33             oil-=now.v,need-=now.v;  //否则全部使用
34         }
35         if(i==n+1)  //如果已经到达终点
36         {
37             while(!q.empty())  //把所有多余的油都转售出去
38             {
39                 now=q.front();  q.pop_front();
40                 ans-=now.v*now.cost;
41             }
42             printf("%.2lf",ans);
43             return 0;
44         }
45         while(!q.empty() && q.back().cost>p[i])  //这一步是剔除已购买的油中的太贵的油,用该地较便宜的油替代,维护队列单调性
46         {
47             now=q.back();  q.pop_back();
48             oil-=now.v,ans-=now.v*now.cost;  //如果购买的油的价钱高于当地就转卖,只剩下便宜的油
49         }
50         ans+=(c-oil)*p[i],q.push_back({p[i],c-oil}),oil=c;  //将新购买的油加入队列,统计花费
51     }
52 return 0;
53 }

 

不注释的代码(点击左上角一键复制)——

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<queue>
 4 using namespace std;
 5 const int N=505;
 6 double c,d1,d2,oil,ans,d[N],p[N];
 7 struct node{ double cost,v; }now;
 8 int n;
 9 deque<node> q;
10 int main()
11 {
12     scanf("%lf %lf %lf %lf %d",&d1,&c,&d2,&p[0],&n);
13     d[n+1]=d1;
14     for(int i=1;i<=n;i++)  scanf("%lf %lf",&d[i],&p[i]);
15     for(int i=2;i<=n+1;i++)
16         if(d[i]-d[i-1]>c*d2){ printf("No Solution"); return 0; }
17     ans=p[0]*c,oil=c;
18     q.push_back({p[0],c});
19     for(int i=1;i<=n+1;i++)
20     {
21         double dis=d[i]-d[i-1],need=dis/d2;
22         while(!q.empty() && need>0)
23         {
24             now=q.front(); q.pop_front();
25             if(now.v>need)
26             {
27                 oil-=need,now.v-=need;
28                 q.push_front(now);
29                 break;
30             }
31             oil-=now.v,need-=now.v;
32         }
33         if(i==n+1)
34         {
35             while(!q.empty())
36             {
37                 now=q.front();  q.pop_front();
38                 ans-=now.v*now.cost;
39             }
40             printf("%.2lf",ans);
41             return 0;
42         }
43         while(!q.empty() && q.back().cost>p[i])
44         {
45             now=q.back();  q.pop_back();
46             oil-=now.v,ans-=now.v*now.cost;
47         }
48         ans+=(c-oil)*p[i],q.push_back({p[i],c-oil}),oil=c;
49     }
50 return 0;
51 }

 

 

     

标签:oil,队列,back,int,ans,front,now,旅行家,单调
来源: https://www.cnblogs.com/leaf-2234/p/14380498.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有