题面&测评链接:
解法:
思路
分析题目。思考,如何用最少代价达到目的。
先明确一点:第 1 个加油站一定要加油,第 n 个加油站一定不加油。
再来想想,设 为第 i 个加油站的价格,如果在第 个加油站加的话,在哪里加下一次油呢?如果存在一个 ,使得在满足 , 的情况下 达到最小值,那就说明 y 加油站比 x 加油站便宜,既然如此,那y以后的油就在 y 加油站买就好了。
于是我们就有了如下贪心思路:
- 对于 x 加油站,我们确定要在这个加油站加油。(最开始 )
- 找到一个 y 加油站,使得在满足 , 的情况下 达到最小值。
- 我们花钱买油跑到 y 加油站。
- ,把 y 的值赋值给 x。
- 如果 ,转至第一步。
- 输出答案,结束。
备注
-
数据范围要注意。我们看题可知:
对于所有测试数据保证:,,,。
考虑答案最大是多少,思考最不利情况:即油的单价最贵,路程最远,每升油跑的距离最少——,,,,此时答案为:,很明显: 类型装不下了,要开 。
-
既然第 n 个加油站一定不加油,我们不妨设第 n 个加油站的油的单价为 0,即。这样根据贪心思路,最后一次买油必定是买到第 n 个加油站。
AC 代码:
#include<bits/stdc++.h>
#define ll long long
#define lf double
using namespace std;
const int N=100002;
ll n,d,w[N],price[N],loc=1,min_price[N],total_w,km,ans;
inline ll max_(ll AA,ll BB)
{//因为<algorithm>头文件中的max函数的参数只能是int类型,所以只能自己手打一个了。
return (AA>BB?AA:BB);
}
int main()
{
scanf("%lld%lld",&n,&d);
for(ll i=2;i<=n;i++)
scanf("%lld",&w[i]);//w[i]:从 i-1 站点到 i 站点的距离
for(ll j=1;j<=n-1;j++)//最后一个加油站的单价不读了,正好就可以空着为0
scanf("%lld",&price[j]);
ll i=1;
while(loc<n)//loc即前面说的x站点
{
i++;//找一个合适的y站点,i就是y
total_w+=w[i];//total_w:这次买油要跑的公里数。
if(price[i]<price[loc])//若符合条件
{
//购买
total_w-=km;//km即每次买完油跑到目标站点不加油后还能跑的公里数
if(total_w<=0)
{
km=(-1)*total_w;
total_w=0;
}
else
{
ll L=ceil((double)total_w/d);//L是这次买油要买几升。
km=L*d-total_w;
total_w=0;
ans+=L*price[loc];
}
loc=i;
}
}
printf("%lld",ans);
return 0;
}
对于程序实现后复杂度的问题,因为存储以及计算都是线性的,所以时间复杂度:,空间复杂度也是:。,所以可以过。