作为一个没有考过普及组的蒟蒻,做提高组的题还是很恶心的。。。
其实我打完代码都不知道自己在写什么,感觉自己的思路很奇怪的,就来发一篇题解
思路分析
如果按照题目的来写,就是到一个加油站,看看要加多少油。
而我的思路是:不管怎样,只要到一个加油站,就把车上的油塞满。如果某个加油站的油很贵,那么到了下一个便宜的加油站,就把上一个加油站剩下的油全部退掉,在用这个加油站的油填满油箱。为了得到更多退油得到的钱,先耗便宜的油。
总结:
1.每到一个加油站,就加满油。
2.到第i个加油站就把油箱里所有>p[i]的油退掉,换成价格为p[i]的油
3.开车时,用最便宜的油
代码分析
变量
1.用一个结构体记录每种油的价格和有多少在油箱。
2.用数组d记录第i个加油站距离出发点的距离,其中d[0]=0,d[n+1]=D1。
3.用变量len记录油箱里有几种油。
遍历
范围:从1到n+1。
内容1:减掉从上一个加油站来消耗的油。注意要从便宜的开始耗,如果不够再换贵的。如果没油了就No Solution并return。
内容2:加油和退油。注意一些细节。(见后面的代码)
AC代码
相信不会有人喜欢上面的一通分析吧,那么,你们喜欢的代码来了——
#include<cstdio>
using namespace std;
int n,len=0;//如上所述
struct LLLL{//结构体
double price;
double sum;
}l[10];
double s,c,dis,ans=0;//s就是D1,dis就是D2
double d[10],p[10];
int main(){
scanf("%lf%lf%lf%lf%d",&s,&c,&dis,&p[0],&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&d[i],&p[i]);
l[0].sum=c;//初始化
l[0].price=p[0];
ans=c*p[0];
len++;
d[n+1]=s;
for(int i=1;i<(n+2);i++){//遍历
double lll=(d[i]-d[i-1])/dis;//需要用的油量
double lll1=lll;//复制一份
bool flag=1;
while(len){//只要还有油
if(l[0].sum<lll){//不够
len--;lll-=l[0].sum;//都减掉
for(int k=0;k<len;k++){//往前挪一位,这样只用看l[0]
l[k].price=l[k+1].price;
l[k].sum=l[k+1].sum;
}
}
else{//够了
l[0].sum-=lll;
flag=0;//记录
break;
}
}
if(flag){//没油了qwq
printf("No Solution");
return 0;//直接返回
}
flag=1;//再赋成true
for(int j=0;j<len;j++){
if(p[i]<l[j].price){//比后面的都小
ans-=(l[j].sum*l[j].price);//退油,注意要从j开始退
for(int k=j+1;k<len;k++){
l[j].sum+=l[k].sum;//加油,注意l[j]是保留下来的,不用再加一次
ans-=(l[k].sum*l[k].price);//后面全退掉
}
l[j].sum+=lll1;//还要加上开车耗掉的油
l[j].price=p[i];//价钱记住
ans+=l[j].price*l[j].sum;//付钱
len=j+1;//注意是j+1,我如果这里没出问题就一遍过了qwq
flag=0;//记录
break;//返回
}
}
if(flag){//如果比所有油都贵
l[len].sum=lll1;//只用加开车耗掉的油
ans+=p[i]*lll1;//付钱
l[len].price=p[i];//价钱记住
len++;//记录多了一种油
}
}
printf("%.2lf",ans);//输出,注意格式
return 0; //华丽结束
}
发题解不仅可以帮助别人,还可以帮自己梳理思路。不过写题解还是挺累的,别忘了点个赞再走哟~