[NOIP1999 提高组] 旅行家的预算

题目描述

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

输入格式

第一行,D_1D1​,CC,D_2D2​,PP,NN。

接下来有 NN 行。

第 i+1i+1 行,两个数字,油站 ii 离出发点的距离 D_iDi​ 和每升汽油价格 P_iPi​。

输出格式

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

输入输出样例

输入 #1复制

275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2

输出 #1复制

26.95

说明/提示

N \le 6N≤6,其余数字 \le 500≤500。

NOIP1999 普及组第三题、提高组第三题

作为一个没有考过普及组的蒟蒻,做提高组的题还是很恶心的。。。

其实我打完代码都不知道自己在写什么,感觉自己的思路很奇怪的,就来发一篇题解

思路分析

如果按照题目的来写,就是到一个加油站,看看要加多少油。

而我的思路是:不管怎样,只要到一个加油站,就把车上的油塞满。如果某个加油站的油很贵,那么到了下一个便宜的加油站,就把上一个加油站剩下的油全部退掉,在用这个加油站的油填满油箱。为了得到更多退油得到的钱,先耗便宜的油

总结:

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; //华丽结束
}

发题解不仅可以帮助别人,还可以帮自己梳理思路。不过写题解还是挺累的,别忘了点个赞再走哟~

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值