题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离
、汽车油箱的容量
(以升为单位)、每升汽油能行驶的距离
、出发点每升汽油价格
和沿途油站数
(
可以为零),油站
离出发点的距离
、每升汽油价格
(
)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出No Solution
。
输入格式
第一行, , , , , 。
接下来有 行。
第 行,两个数字,油站 离出发点的距离 和每升汽油价格 。
输出格式
所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出No Solution
。
输入输出样例
输入 #1
275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2
输出 #1
26.95
说明/提示
其余数字 。
思路
我一开始做的时候,这么水的模拟+贪心题怎么是绿题。
就开始了。
首先,如果在这个点能够到达的点中没有比这个点的
更小的了,就找一个最小的开过去。
可是还有一个误区,就是这样:
这些都是点 能够到达的点。
比较一下以下两种方案:
- 直接从 到
- 从 到 ,从 到 ,从 到
应该是方案 更好。
所以,只要在这个点所能到达的点中直接跳到离这个点最近的并且 的点上就可以了。
代码
#include<bits/stdc++.h>
#define maxn 10000
using namespace std;
double l,c,d,p[maxn],w[maxn];
int n;
int main(){
scanf("%lf%lf%lf%lf%d",&l,&c,&d,&p[0],&n);
w[0]=0;
double x=c*d;
for(int i=1;i<=n;i++){
scanf("%lf%lf",&w[i],&p[i]);
if(w[i]-w[i-1]>x){
cout<<"No Solution";
return 0;
}
}
w[++n]=l;
p[n]=0x3fffffff;
double ans=0;
int now=0;
while(now!=n){
int k=now;
for(int j=now+1;j<=n&&w[j]-w[now]<=x;j++)
if(p[j]<=p[k]||j==n){
k=j;
break;//第一个!!!
}
if(k==now){//没有比P{now}更小的Px了
k=now+1;
for(int j=now+2;j<=n&&w[j]-w[now]<=x;j++)
if(p[j]<=p[k]){
k=j;
}
}
ans+=(w[k]-w[now])/d*p[now];
now=k;
}
printf("%0.2lf",ans);
return 0;
}
别急着抄代码,这还不是正解。
因为,还有一种情况,如果你要去的下一个点的 比当前点的 小,那就应该加满油,到下一个点的时候稍加一点油,就会更划算。
代码
#include<bits/stdc++.h>
#define maxn 8
using namespace std;
double l,c,d,p[maxn],w[maxn];
double y[maxn];
int n;
int main(){
scanf("%lf%lf%lf%lf%d",&l,&c,&d,&p[0],&n);
w[0]=0;
double x=c*d;
for(int i=1;i<=n;i++){
scanf("%lf%lf",&w[i],&p[i]);
if(w[i]-w[i-1]>x){
cout<<"No Solution";
return 0;
}
}
w[++n]=l;
p[n]=0x3fffffff;
double ans=0,youliang=0;
int now=0;
while(now!=n){
int k=now;
for(int j=now+1;j<=n&&w[j]-w[now]<=x;j++){
if(p[j]<=p[k]||j==n){
k=j;
ans+=((w[k]-w[now])/d-youliang)*p[now];
youliang=0;
break;
}
}
if(k==now){
k=now+1;
for(int j=now+2;j<=n&&w[j]-w[now]<=x;j++)
if(p[j]<=p[k]){
k=j;
}
ans+=(c-youliang)*p[now];
youliang=c-youliang-(w[k]-w[now])/d;
}
now=k;
}
printf("%0.2lf",ans);
return 0;
}