这题太复杂了,能否全A看数据。。。
很好的一道模拟贪心题
算法原理(优先级)如下:
1.枚举途中经过的加油站,每经过一个加油站,计算一次花费
2.在一个加油站所需要加的油,就是能够支持它到达下一个油价比它低的加油站的量;
3.如果在这个加油站即使加满油,都不能到达一个比它油价低的加油站,(1)就把油箱加满,前往能够到达的加油站中油价最低的那个;(2)或者直接到终点;
4.如果在这个加油站即使加满油,都不能到达任意一个加油站,也不能到达终点城市,说明无解;
-
先考虑2再考虑3,2一定划算,且无后续性
-
第二点:注意不仅要省钱,还要是最近的加油站(尽早省钱美滋滋)
-
第三点:前提是不省钱,注意要考虑直接到终点的情形
-
第三点:为什么要加满油?因为这样可以减少在下一个加油站(价格更贵)所需要加的油量。
贪心思路就是这样,能否实现看本事
first try : 60
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double d1,c,d2,n,p1,lc,ans;
struct liu{
double d,p,h;
}a[105];
int main() {
scanf("%lf%lf%lf%lf%lf",&d1,&c,&d2,&p1,&n);
lc=c*d2;
for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].h,&a[i].d,&a[i].p);
double i=0,yq=p1;
while(i<d1) {
double t=i+lc,_min=1e9;
int bh=0;
for(int j=1;j<=n;j++) {
if(a[j].d>i&&a[j].d<=t&&a[j].p<_min&&a[j].d<d1) _min=a[j].p,bh=j;
}
if(bh==0) {
if(t>=d1) {
ans+=(d1-i)*yq/d2;
break;
}
else {
printf("No solution");
return 0;
}
}
else {
if(t>=d1) {
if(yq<=_min) {
ans+=(d1-i)*yq/d2;
break;
}
}
ans+=(a[bh].d-i)*yq/d2,i=a[bh].d,yq=a[bh].p;
}
}
printf("%.2lf",ans);
}
}
错因:
1.未考虑是否省钱
2.不是选的最近的油站,而是选最便宜的
3.未考虑剩余油
样例输入:
475.6 11.9 27.4 14.98 6
102.0 9.99
220.0 13.29
256.3 14.79
275.0 10.29
277.6 11.29
381.8 10.09
样例输出:
192.15
真实输出:
192.32
于是我权衡了网上思路,进行第二次尝试
正解:
second try : 100
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
double d1,c,d2,n,p1,lc,ans,yx;
struct liu{
double d,p;
}a[10005];
int main() {
scanf("%lf%lf%lf%lf%lf",&d1,&c,&d2,&p1,&n);
lc=c*d2;
for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].d,&a[i].p);
double i=0,yq=p1;
while(i<d1) {
double t=i+lc,_min=1e9;
int bh=0;
for(int j=1;j<=n;j++) {//在范围内寻找能省钱且最近的
if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<yq&&a[j].d<_min) {
bh=j,_min=a[j].d;
}
}
if(bh!=0) ans+=((a[bh].d-i)*yq-yx)/d2,i=a[bh].d,yq=a[bh].p,yx=0;
//剩余油不可能直接使到达
//不能找到,分为能否直接到达终点以及有无后续加油站两方面同时考虑
else {
_min=1e9,bh=0;
for(int j=1;j<=n;j++) {//在范围内寻找最便宜(并不省钱)的加油站
if(a[j].d>i&&a[j].d<=t&&a[j].d<d1&&a[j].p<_min) _min=a[j].p,bh=j;
}
//无后续加油站且无法直接到达终点
if(bh==0&&t<d1) {
printf("No Solution");
return 0;
}
//能直接到达,最划算
if(t>=d1) {
if(yx<(d1-i)/d2) {
ans+=((d1-i)/d2-yx)*yq;
}
break;
}
//不能直接到达但有后续加油站,先加满(省钱),记录剩余油的多少
//加满和到最便宜的地方是关键
else {
ans+=(c-yx)*yq;
yx=c-(a[bh].d-i)/d2;
yq=a[bh].p,i=a[bh].d;
}
}
}
printf("%.2lf",ans);
}
写得算完整了,欢迎打脸质疑我
仔细品味两次找油站!第一次是省钱且最近,第二次只是最便宜