题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入输出格式
输入格式:
第一行,D1,C,D2,P,N。
接下来有N行。
第i+1行,两个数字,油站i离出发点的距离Di和每升汽油价格Pi。
输出格式:
所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
题目解析
看好多人用队列做的,然而并不想用
可以这样想,每次遇到加油站就把油箱里的“贵油”卖掉,再把油箱加满地沟油。得出的结果是一样的。
为了方便判断油的价格,rk[x]表示第x个油站的价格排名,bag[x]表示排名为x的油在油箱里有多少,注意细节模拟就可以了
Code
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int MAXN = 10; struct Station { int id; double price; friend bool operator < (Station x,Station y) { return x.price < y.price; } } s[MAXN]; struct Oil { double sum; double price; double rk; }; int n; double cub,ech,ans;//分别是油箱容量,每升油跑多远,共多少钱 double p[MAXN],dis[MAXN],bag[MAXN];//价格 离起点的距离 油箱 int rk[MAXN]; int main() { double tmp; scanf("%lf%lf%lf%lf%d",&tmp,&cub,&ech,&p[1],&n); dis[n+2] = tmp; s[1].id = 1; s[1].price = p[1]; n++; for(int i = 2;i <= n;i++) { scanf("%lf%lf",&dis[i],&p[i]); s[i].price = p[i]; s[i].id = i; p[i] = s[i].price; if(dis[i]-dis[i-1] > cub*ech) { printf("No Solution "); return 0; } } sort(s+1,s+1+n); for(int i = 1;i <= n;i++) { rk[s[i].id] = i; } // for(int i = 1;i <= n;i++) { // cout<<i<<" "<<p[i]<<" "<<dis[i]<<" "<<rk[i]<<endl; // } for(int i = 1;i <= n+1;i++) { double tot = 0; double need = (dis[i]-dis[i-1]) / ech; for(int j = 1;j <= n;j++) { if(need >= bag[j]) need -= bag[j],bag[j] = 0; else if(need) { bag[j] -= need;need=0; break; } } if(i == n+1) break; for(int j = 1;j <= n;j++) { if(!bag[rk[j]]) continue; if(rk[i] < rk[j]) { ans -= bag[rk[j]] * (p[j]-p[i]); bag[rk[i]] += bag[rk[j]]; bag[rk[j]] = 0; } tot += bag[rk[j]]; } bag[rk[i]] += cub - tot; ans += (cub-tot) * p[i]; // for(int j = 1;j <= n;j++) printf("%.2lf ",bag[j]); // cout<<" with ans is: "<<ans<<endl; } for(int i = 1;i <= n;i++) ans -= bag[rk[i]] * p[i]; printf("%.2lf ",ans); return 0; }