题目:
https://www.luogu.org/problemnew/show/1016
这道题好麻烦啊~~~~
贪心策略:
尽可能少花钱(废话),能省就省; 这才是贪心嘛
当前点为i;
将之前的所有加油站压入一个优先队列;
对于两个加油站之间的距离,我们可以”一次”到位,也可以”分段”到位;
ps : 话说,n最大是6……,那代码的时间复杂度是不是O(1)的呢?<-_<-;
用单调队列也可以,但是n最多是6,多个log又有什么不可以的呢?qwq
具体思路代码中有:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=1001;
struct hh
{
double pos,cost;
}ma[MAXN];
priority_queue<hh>q;
double D1,C,can,P,ans;
bool flag=0;
int n;
bool operator < (hh a,hh b)
{
return a.cost > b.cost;
}
void solve()
{
cin>>D1>>C>>can>>P>>n;
q.push((hh){0,P});
for(int i=1;i<=n;i++)
cin>>ma[i].pos>>ma[i].cost;
ma[n+1]=(hh){D1,0};
n++;
for(int i=1;i<=n;i++)
{
double last=ma[i].pos-can*C,d=-1;//last是能到达i的最远位置;
flag=0;
while(!q.empty())
{
hh u=q.top();
if(u.pos>=last)//是否可以到达当前地点;
{
if(d==-1) ans+=((ma[i].pos-ma[i-1].pos))*u.cost;//直接到达;
else ans+=((ma[i].pos-d))*u.cost;//分段到达;
flag=1;//标记可以到达
q.push(ma[i]);//加进去;
break;
}
else //如果到不了,装满油,看看最远可以到哪里;
{
q.pop();//弃掉;
d=can*C+u.pos;
if(d>ma[i-1].pos)
ans+=((d-ma[i-1].pos))*u.cost;
else d=-1;//到不了;
}
}
if(!flag)//如果到不了;
{
cout<<"No Solution"<<endl;
return;
}
}
printf("%.2f\n",ans/can);//最后除以can;
return;
}
int main()
{
solve();
return 0;
}