For each case, the first line contains 4 positive numbers: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=20), the average distance per unit gas that the car can run; and N (<= 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: Pi, the unit gas price, and Di (<=D), the distance between this station and Hangzhou, for i=1,...N. All the numbers in a line are separated by a space.
For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print "The maximum travel distance = X" where X is the maximum possible distance the car can run, accurate up to 2 decimal places.
50 1300 12 8 6.00 1250 7.00 600 7.00 150 7.10 0 7.20 200 7.50 400 7.30 1000 6.85 300 50 1300 12 2 7.10 0 7.00 600
749.17 The maximum travel distance = 1200.00
#include<iostream> #include<algorithm> #include<cstring> using namespace std; struct gas_stations { double pi; int di; }; bool compare(gas_stations g1, gas_stations g2) { return g1.pi < g2.pi; } int main() { int C, D, Davg, N; double cost; while (cin>>C>>D>>Davg>>N) { gas_stations* G = new gas_stations[N]; for (int i = 0; i < N; i++)//输入加油站位置、价格 cin >> G[i].pi >> G[i].di; sort(G, G + N,compare);//按价格排序 cost = 0;//记录花费 int max = C * Davg, need, dis; int* flag = new int[D+10]; memset(flag, 0, (D + 10) * sizeof(int)); //关键代码 for (int i = 0; i < N; i++) { //如果到终点距离<max,只需加上足够走到终点的油 need = (G[i].di + max < D ? max : D - G[i].di); dis = 0; //记录有多长距离需要该加油站的油 for (int j = G[i].di; j < G[i].di + need; j++) { if (flag[j] == 0) { flag[j] = 1; dis++; } } cost += dis / (Davg * 1.0) * G[i].pi; //加上在该加油站的花销 } //输出 cout.precision(2); int i; for (i = 0; i < D; i++) {//有的路程没有被覆盖到说明走不到这里 if (flag[i] == 0) { cout << "The maximum travel distance = " <<fixed<< (double)i << endl; break; } } if (i == D)//到达目的地 cout <<fixed<< cost << endl; delete[] G, flag; } return 0; }
#define _CRT_SECURE_NO_WARNINGS (842)#include <algorithm> using namespace std; const int MAXN = 500 + 10; struct Station_t { double price; double dest; double cov;//最远能覆盖到的坐标点 bool operator<(const Station_t x) { return dest < x.dest; } }; Station_t gStation[MAXN]; int main() { int capacity, dest, davg, n; begin: while (scanf("%d%d%d%d", &capacity, &dest, &davg, &n) != EOF) { double eDest = (double)capacity * davg;//eDest表示每次油箱装满能走得最远距离 for (int i = 0; i < n; i++) { scanf("%lf%lf", &gStation[i].price, &gStation[i].dest); gStation[i].cov = gStation[i].dest + eDest; } gStation[n].dest = dest; gStation[n].price = 0; sort(gStation, gStation + n); for (int i = 0; i < n; i++) {//判断最终能否到达加油站 if (gStation[i].cov < gStation[i + 1].dest) { printf("The maximum travel distance = %.2lf\n", gStation[i].cov); goto begin; } } int index = 0, nextIndex = 0;//index表示当前所在加油站的标识 double cost = 0, curMass = 0, needMass;//成本、当前油量、到达下一站需要的油量 while (index < n) { double minPrice = gStation[index].price; nextIndex = index; //找油箱加满后能够行驶的距离范围内比当前加油站油价便宜的最近的加油站 for (int i = index + 1; i <= n && gStation[i].dest <= gStation[index].cov; i++) { if (gStation[i].price <= minPrice) { minPrice = gStation[i].price; nextIndex = i; break; } } //如果找到了可行驶距离范围内比当前所在加油站拥有更低油价的加油站,那么只需要使油量够行驶至此加油站即可 if (nextIndex != index) {//找到了更便宜的油站 needMass = (gStation[nextIndex].dest - gStation[index].dest) / davg;//行驶到此站需要的油量 if (curMass < needMass) {//查看油量是否够用,不够用则加油至刚好能到这一站 cost += (needMass - curMass) * gStation[index].price; curMass = 0;//到达下一站,油量刚好归零 } else {//油量够用,不用再额外加油 curMass -= needMass; } index = nextIndex; } else {//没有找到价格更低的加油站,把油加满,走到下个加油站 cost += (capacity - curMass) * gStation[index].price; curMass = capacity; needMass = (gStation[index + 1].dest - gStation[index].dest) / davg; curMass -= needMass; index++; } } printf("%.2lf\n", cost); } return 0; }
#include <stdio.h> int main() { double cmax,d,davg; int n; while(scanf("%lf%lf%lf%d",&cmax,&d,&davg,&n)!=EOF) { double price[1000]; double dist[1000]; double dmax=cmax*davg; double gross=0; int now=n; price[n]=2000000000; price[n+1]=2000000001; dist[n]=d; dist[n+1]=d+dmax; for(int i=0; i<n; i++) { scanf("%lf%lf",&price[i],&dist[i]); if(dist[i]==0 && price[i]<price[now]) now=i; } while(now!=n) { int cheapest=n+1; int cheaper=n+1; for(int i=0; i<=n; i++) { if(dist[i]>dist[now] && dist[i]-dist[now]<=dmax && price[i]<price[cheapest]) cheapest=i; if(dist[i]>dist[now] && dist[i]-dist[now]<=dmax && ((price[i]<price[now] && dist[i]<dist[cheaper]) || (dist[i]==dist[cheaper] && price[i]<price[cheaper]))) cheaper=i; } if(cheapest==n+1) break; else if(cheaper!=n+1) { gross+=price[now]*(dist[cheaper]-dist[now])/davg; now=cheaper; } else if(dist[now]+dmax>=d) { gross+=price[now]*(d-dist[now])/davg; now=n; } else { gross+=price[now]*(dist[cheapest]-dist[now])/davg-(price[cheapest]-price[now])*(dist[now]+dmax-dist[cheapest])/davg; now=cheapest; } } if(now==n) printf("%.2lf\n",gross); else printf("The maximum travel distance = %.2lf\n",dist[now]+dmax); } return 0; }
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; struct station{ double p;//单位油价格(不同) double d;//本站和杭州之间的距离 }; bool cmp(station x,station y){ if(x.d==y.d)//距离相同比价格 return x.p<y.p; else return x.d<y.d; } int main(){//不要用float,全部double double Cmax;//油箱最大容量 double D;//杭州和目的城市之间的距离 double Davg;//单位***驶里程(相同) int n;//加油站的总数 while(cin>>Cmax>>D>>Davg>>n){ station sta[n+1]; for(int i=0;i<n;i++) cin>>sta[i].p>>sta[i].d; sta[n].p=0,sta[n].d=D;//增加终点站 sort(sta,sta+n,cmp); double cap=0;//剩余油量 double x=0;//行驶总里程 double price=0;//总油费 double Dmax=Cmax*Davg;//满油最大里程 for(int i=0;i<n;i++){ if(Dmax<(sta[i+1].d-sta[i].d)){//加满油也到不了下一站 printf("The maximum travel distance = %.2f\n",x+Dmax);//输出最大行驶历程 break; } int cheapest=i+1;//标记油价最便宜的站 int nearest=i+1;//标记便宜且距离最近的站 int pmin=sta[i+1].p;//标记前方最低油价 for(int j=i+1;Dmax>=(sta[j].d-sta[i].d)&&j<=n;j++){//在所能到达的所有加油站中(包括终点站) if(sta[j].p<=pmin){//寻找油价最便宜的站 cheapest=j; pmin=sta[j].p; } } for(int j=i+1;Dmax>=(sta[j].d-sta[i].d)&&j<=n;j++){//在所能到达的所有加油站中(包括终点站) if(sta[j].p<=sta[i].p){//寻找便宜且距离最近的站 nearest=j; break; } } if(sta[i].p<pmin){//当前站油价最便宜,加满油去下一个油价最便宜的站 price=price+(Cmax-cap)*sta[i].p;//油费++ cap=Cmax;//加满 x=x+sta[cheapest].d-sta[i].d;//里程++ cap=cap-(sta[cheapest].d-sta[i].d)/Davg;//油量-- i=cheapest-1;//i++-->cheapest } else{//前面有油价小于或等于当前油价的站,视情况加油去距离最近的便宜站 if(cap*Davg<(sta[nearest].d-sta[i].d)){//如果剩余油到不了最近便宜站 price=price+((sta[nearest].d-sta[i].d)/Davg-cap)*sta[i].p;//油费++ cap=(sta[nearest].d-sta[i].d)/Davg;//加刚好能到最近便宜站的油 } x=x+sta[nearest].d-sta[i].d;//里程++ cap=cap-(sta[nearest].d-sta[i].d)/Davg;//油量-- i=nearest-1;//i++-->nearest } } if(x==D)//到达终点站 printf("%.2f\n",price); } return 0; }
/* 核心思路:利用贪心策略,从最便宜的加油站开始,每个加油站加的油最多能走cmax*davg路程. 利用一个30000大小的flag数组记录是否有重合区域 */ #include<cstdio> #include<algorithm> using namespace std; struct sta{ double pi; int di; bool operator < (const sta& b) const{ return pi<b.pi; } }a[501]; int main(){ int cmax, d, davg, n; double sum; while(scanf("%d %d %d %d", &cmax, &d, &davg, &n)!=EOF){ for(int i=0; i<n; i++) scanf("%lf %d", &a[i].pi, &a[i].di); sort(a, a+n); // sum = 0;//记录花费 int flag[30001]={0}, max = cmax*davg, tmp, cnt; for(int i=0; i<n; i++){ tmp = (a[i].di+max<d?max:d-a[i].di); //如果到终点距离<max,只需加上足够走到终点的油 cnt = 0; //记录有多长距离需要该加油站的油 for(int j=a[i].di; j<a[i].di+tmp; j++){ if(flag[j]==0){ flag[j] = 1; cnt++; } } sum += cnt/(davg*1.0)*a[i].pi; //加上在该加油站的花销 } //check int i; for(i=0; i<d; i++){ //有的路程没有被覆盖到说明走不到这里 if(flag[i]==0){ printf("The maximum travel distance = %.2lf\n", (double)i); break; } } if(i==d){ printf("%.2lf\n",sum); } } return 0; }
#include<stdio.h> #include<algorithm> using namespace std; typedef struct station{ double price; double dis; bool operator <(const station &A) const { return dis<A.dis; } }station; int main(){ station buf[501]; int i,j,n; double cmax,d,davg,maxdis,ans; while(scanf("%lf%lf%lf%d",&cmax,&d,&davg,&n)!=EOF){ ans=0; maxdis=cmax*davg; for(i=0;i<n;i++) scanf("%lf%lf",&buf[i].price,&buf[i].dis); buf[n].dis=d; sort(buf,buf+n); if(buf[0].dis!=0){ printf("The maximum travel distance = 0.00\n"); continue; } double curpos=0; double curoil=0; for(i=0;i<n;i++){ curpos=buf[i].dis; if(curpos+maxdis<buf[i+1].dis){ printf("The maximum travel distance = %.2lf\n",curpos+maxdis); break; } if(i>0) curoil-=(buf[i].dis-buf[i-1].dis)/davg; double curdis=0; bool ischeap=false; for(j=i+1;j<n;j++){ curdis=buf[j].dis-buf[i].dis; if(curdis>maxdis) break; if(buf[j].price<buf[i].price){ double temp=(buf[j].dis-buf[i].dis)/davg; if(temp>curoil){ ans+=(temp-curoil)*buf[i].price; curoil=temp; } ischeap=true; break; } } if(!ischeap){ if(curpos+maxdis>=d){ ans+=((d-curpos)/davg-curoil)*buf[i].price; printf("%.2lf\n",ans); break; } else{ ans+=(cmax-curoil)*buf[i].price; curoil=cmax; } } } } return 0; } 在网上看了一些思路才会做这题,利用贪心算法,每次走一个加油站,记录当前的距离和油量, 然后查看最大距离以内的加油站有没有比当前站便宜的,若有,则查看油量, 把油量加到足够到达便宜的站,若没有,则看油量够不够到终点,不够则把油加满。 在到达没站的过程中若油量不够到达最近的一站,则输出最大距离。 特殊情况:没有距离为0的加油站。 结果实现过程中没想到漏掉一个换行符和一个break弄了我很长时间。 给的测点又看不完全。心塞。。。
/* 说下思路,这题写了我一天 贪心的思想,我们将终点看做一个价格为0,距离为最大值的车站 读入所有车站,按照距离从小到大排序,如果距离相同,按照价格从小到大,因为距离相同的油站我们取最便宜的 然后默认我们从起始的位置,也就是0起点的油站开始走 特殊情况: 如果起始点没有油站,那么车无法走,直接认为无解。 从当前车站往后搜寻比当前油站价格便宜的。 1.如果有比当前价格便宜的,那么加油到能够开到这个油站,然后继续寻找下一个更便宜的油站 2.如果没有,那么记录能够到达的油站中相对价格最低的,认为从当前油站加满油直接开到这个油站 这个很重要,就是因为这个问题卡了我一整天 3.如果没有找到比当前价格便宜的油站并且也没找到相对价格便宜的油站,那就退出,用当前油站的距离加上 满油能走的最大距离,输出 */ #include <bits/stdc++.h> using namespace std; struct station{ double price,dis; }; bool cmp(station a,station b){ if(a.dis==b.dis){ return a.price<b.price; }else{ return a.dis < b.dis; } } const double inf = 999999999; int main(){ double cmax,d,davg; int n; cin>>cmax>>d>>davg>>n; station sta[n+1]; sta[0].price = 0;sta[0].dis = d; for(int i=1;i<=n;i++){ cin>>sta[i].price>>sta[i].dis; } sort(sta,sta+n+1,cmp); double nowprice = 0.0,nowdis = 0.0; double totalprice = 0.0,leftdis = 0.0; // leftdis 用于表示当前最便宜的油还能走多久 if(sta[0].dis!=0){ cout<<"The maximum travel distance = 0.0"; return 0; }else{ nowprice = sta[0].price; } while(nowdis!=d){ double maxdis = cmax*davg+nowdis; // 当前满油能走多远 double minprice = inf; double minpriceDis = 0.0; int flag = 0; for(int i=1;i<=n&&sta[i].dis<=maxdis;i++){ if(sta[i].dis<=nowdis){ // 若油站已经走过 continue; }else{ if(sta[i].price<nowprice){ // 找到比当前价格便宜的油站 flag = 1; totalprice += (sta[i].dis-nowdis-leftdis)/davg * nowprice; leftdis = 0.0; nowdis = sta[i].dis; nowprice = sta[i].price; break; }else if(sta[i].price<minprice){ // 记录当前可以到达的价格相对较小的油站 minprice = sta[i].price; minpriceDis = sta[i].dis; } } } if(flag == 0 && minprice != inf){ // 未找到比当前价格便宜的油站,但是有相对便宜的 totalprice += (nowprice * (cmax - leftdis/davg)); leftdis = cmax*davg+nowdis - minpriceDis; // 计算便宜的=又还能走多远 nowprice = minprice; nowdis = minpriceDis; } if(flag == 0 && minprice == inf){ // 未找到比当前便宜的油站并且也不能找到最便宜的 printf("The maximum travel distance = %.2f",maxdis); return 0; } } printf("%.2f\n",totalprice); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; typedef struct station{ double Pi; double Di; }; typedef struct carbox{ //车上每一款油的余量和价格 double gas; double price; }; bool comp(station x,station y){ return x.Di<y.Di; } int main(){ double Cmax,D,Davg; int N; station sta[500]; carbox box[500]; while(cin>>Cmax>>D>>Davg>>N){ for(int i=0;i<N;i++){ cin>>sta[i].Pi>>sta[i].Di; } sort(sta,sta+N,comp); double x=0; //先检查是否能到终点 for(int i=0;i<N;i++){ if(x+Cmax*Davg>=sta[i].Di){ x=sta[i].Di; if(i==N-1){ if(x+Cmax*Davg>=D){ x=D; } else{ x+=Cmax*Davg; } } } else{ x+=Cmax*Davg; break; } } if(x!=D){ //检查完成,开始进入计算 printf("The maximum travel distance = %.2f",x); continue; } int hp=0,ep=0; //油箱的油按价格递增排列,hp指向目前有余量最便宜的油 box[0].gas=0; //ep指向目前有余量最贵的油 box[0].price=sta[0].Pi; x=0; double c=0; double sum=0; for(int i=0;i<N;i++){ double y=sta[i].Di-x; //记录行驶路程 x=sta[i].Di; while(y>0){ //耗油 if(y>=box[hp].gas*Davg){ y-=box[hp].gas*Davg; c-=box[hp].gas; hp++; } else{ box[hp].gas-=y/Davg; c-=y/Davg; y=0; } } for(int j=hp;j<=ep;j++){ if(box[j].price>=sta[i].Pi){ for(int k=j;k<=ep;k++){ //卖油 sum-=box[k].gas*box[k].price; c-=box[k].gas; } ep=j; //买便宜油 box[j].price=sta[i].Pi; box[j].gas=Cmax-c; sum+=box[j].gas*box[j].price; c=Cmax; } } //虽然这个加油站最贵,但还是买满 if(c<Cmax){ ep++; box[ep].price=sta[i].Pi; box[ep].gas=Cmax-c; sum+=box[ep].gas*box[ep].price; c=Cmax; } } double y=D-x; while(y>0){ //最后消耗 if(y>=box[hp].gas*Davg){ y-=box[hp].gas*Davg; c-=box[hp].gas; hp++; } else{ box[hp].gas-=y/Davg; c-=y/Davg; y=0; } } for(int k=hp;k<=ep;k++){ //最后卖完 sum-=box[k].gas*box[k].price; } printf("%.2f\n",sum); } return 0; }
#include <iostream> #include <algorithm> using namespace std; struct GasStation { double price; int distance; }; bool ComparePrice(GasStation x, GasStation y) { return x.price < y.price; } int main() { int cmax, d, davg, n; while (cin >> cmax >> d >> davg >> n) { double currentprice = 0; // 当前油费 bool tag[d + 1]; // 记录当前有哪段道路是从加油站出发能走的 GasStation gasStation[n]; for (int i = 1; i <= d; ++i) tag[i] = false; for (int i = 0; i < n; ++i) cin >> gasStation[i].price >> gasStation[i].distance; sort(gasStation, gasStation + n, ComparePrice); // 对油价按升序排 for (int i = 0; i < n; ++i) { // 对tag[]进行记录, 并同时计算出 currentprice int currentdistance = 0; // 记录从这个加油站出发要用其油的距离 for (int j = gasStation[i].distance + 1; j <= gasStation[i].distance + cmax * davg; ++j) { if (tag[j] == false) { // 如果 tag[j]为假则可走 tag[j] = true; currentdistance++; } if (j == d || j == gasStation[i].distance + cmax * davg) { // 走到了尽头 currentprice += gasStation[i].price * currentdistance / (davg * 1.0); break; } } } int fill = 1; // tag[]是否全为真的标志位 double journey = 0; for (int i = 1; i <= d; ++i) { if (tag[i] == true) journey++; else { fill = 0; break; } } if (fill) printf("%.2f\n",currentprice); else printf("The maximum travel distance = %.2f\n", journey); } return 0; }
#include<iostream> (720)#include<math.h> #include<cstring> (803)#include<vector> #include<algorithm> using namespace std; /* 贪心: 1.起步时,如果没有距离是0的加油站,肯定走不了 2.在每个加油站都判断在最大油箱行驶距离内是否有比当前油价更便宜的: 如果没有,则加满。并且判断 是否两个加油站的距离大于油箱的最大行驶距离,如果是直接输出;如果不是继续循环。 如果有,则加到那个加油站的油就行了。 */ double Cmax,D,Davg,N,dis,price,gomax,ans,cur;//gomax为油加满的最大行驶距离。ans为最后的输出 。cur为当前的油量 struct station{ double p; double d; station(double pp,double dd):p(pp),d(dd){} inline bool operator <(const station &s)const{ return d<s.d; } };vector<station> vec; int main(){ while(cin>>Cmax>>D>>Davg>>N){ vec.clear(); bool ret=false; gomax=Cmax*Davg;ans=0,cur=0; for(int i=0;i<N;i++){ cin>>price>>dis; vec.push_back(station(price,dis)); }sort(vec.begin(),vec.end());//按距离进行排序 if(vec[0].d!=0){ printf("The maximum travel distance = 0.00\n"); ret=true; }else{ for(int i=0;i<vec.size();i++){ //cout<<"cur:"<<cur<<endl; //cout<<"i:"<<i<<endl; if(i==vec.size()-1){//判断当前油能不能到终点,如果能就break;如果不能则要加一点油。 double needdis=D-vec[i].d; if(needdis<=gomax){ //能到终点 if(cur<needdis/Davg){ ans+=(needdis/Davg-cur)*vec[i].p; //cout<<"plus:"<<(needdis/Davg-cur)*vec[i].p<<endl; } }else{ printf("The maximum travel distance = %.2f\n",vec[i].d+gomax); ret=true; }break; } double min=vec[i].p;int index=i; if(vec[i+1].d-vec[i].d>gomax){//后一个加油站的距离大于油箱的最大行驶距离。 printf("The maximum travel distance = %.2f\n",vec[i].d+gomax); ret=true; break; } for(int j=i+1;j<vec.size();j++){ if(vec[j].d-vec[i].d<=gomax){ if(vec[j].p<min){ index=j;//找到了最近的一个比当前加油站便宜的加油站,加油加到此地就可以了。 break; } }else break; } if(index==i){//说明油箱最大行驶范围内就当前的加油站最便宜-->加满 if((D-vec[i].d)<=gomax){//如果终点就在眼前,加到终点就可以。 if(cur<(D-vec[i].d)/Davg){ ans+=((D-vec[i].d)/Davg-cur)*vec[i].p; }break; } ans+=(Cmax-cur)*vec[i].p; cur=Cmax-(vec[i+1].d-vec[i].d)/Davg; }else{ double costoil=(vec[index].d-vec[i].d)/Davg; //行驶这段距离需要的油 if(costoil<=cur){//如果需要的油小于还剩的油,不用花钱。 cur-=costoil; }else{ double needoil=costoil-cur; ans+=needoil*vec[i].p; //cout<<"plus:"<<needoil*vec[i].p<<endl; cur=0; } i+=(index-i-1);//-1是因为i还要自加1一次; } } } if(!ret)printf("%.2f\n",ans); } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; struct station{ double pri; double dis; bool visited; int index; }; station sta[500]; bool cmp(station x, station y){ if(x.dis==y.dis){ return x.pri<y.pri; } else return x.dis<y.dis; } int main(){ int N; double Cmax,wholeDis, aveDis; while(cin>>Cmax){ cin>>wholeDis>>aveDis>>N; for(int i=0;i<N; i++){ cin>>sta[i].pri>>sta[i].dis; sta[i].visited=false; sta[i].index=i; } sort(sta,sta+N,cmp); double currentDis=0;//当前行驶距离 double currentFuel=0;//当前油量 double wholePri=0;//总费用 double consume=-1;//和目标加油站相差的油量 double cost=-1;//(临时变量用于解释) int temp=-1;//临时变量,当前加油站的编号 int fail=0;//无法到达目的地 int succeed=0;//可以到达目的地 double dif=-1;//(临时变量用于解释) double finalDis=0;//最远行驶距离 double tempPri=-1;//(临时变量用于解释) int next = 0; // for(int i=0; i<N; i++) // cout<<sta[i].pri<<" "<<sta[i].dis<<endl; while(true){ if(succeed) break; int sign=0;//默认到不了更远的加油站 for(int i=next; i<N; i++){ if(currentDis+currentFuel*aveDis>=sta[i].dis) {//能顺利到达下个加油站 sign = 1; sta[i].visited = true; currentFuel -= (sta[i].dis - currentDis) / aveDis;//到达此加油站剩余的油量 currentDis = sta[i].dis;//更新当前位置 temp = i; // cout << "当前位于加油站" << temp << " 当前位置:" << currentDis << " 当前油量:" << currentFuel << endl; //计算下一个要去的加油站 double minPri = 99999999999; int flag = 0;//默认能到达的加油站没有比它价格更小的 for (int j = temp + 1; j < N; j++) { if (currentDis + Cmax * aveDis >= sta[j].dis && !sta[j].visited&&sta[j].pri < sta[i].pri) {//此加油站能到达的,比它价格更小的 next = j; flag = 1; break; } } if (flag) {//加到够到目标站的就行了 if(currentDis + currentFuel*aveDis <sta[next].dis) {//如果当前的油不够到目标站的 consume = (sta[next].dis - currentDis) / aveDis;//需要的油量 dif = (consume - currentFuel); cost = (consume - currentFuel) * sta[i].pri; wholePri += (consume - currentFuel) * sta[i].pri; currentFuel = consume; flag = 0; // cout << "下一站想去:" << next << " 目标位置:" << sta[next].dis << " 需要油量:" << consume << endl; // cout << "加了" << dif << " 花费:" << cost << endl; break; } else{ // cout<<"此加油站不加油"<<endl; break; } } else {//没找到价格更低的,加到下个重点或者全都加满 if (currentDis + currentFuel * aveDis >= wholeDis) {//剩余油足够到达终点 succeed = 1;//不加了 break; } else if (currentDis + Cmax * aveDis >= wholeDis) {//再加一些能到达终点 consume = (wholeDis - currentDis) / aveDis; dif = (consume - currentFuel); cost = (consume - currentFuel) * sta[i].pri; wholePri += (consume - currentFuel) * sta[i].pri; succeed = 1; // cout << "加了" << dif << " 花费:" << cost << endl; break; } else {//加满 dif = (Cmax - currentFuel); cost = (Cmax - currentFuel) * sta[i].pri; wholePri += (Cmax - currentFuel) * sta[i].pri; currentFuel = Cmax; // cout << "加了" << dif << " 花费:" << cost << endl; // cout << "####已加满油####" << endl; next=temp+1; break; } } } } if(sign==0){ finalDis=currentDis+Cmax*aveDis; fail=1; break; } } if(succeed) printf("%.2lf\n",wholePri); if(fail) printf("The maximum travel distance = %.2lf\n",finalDis); } return 0; }
package com.speical.first;
import java.util.Scanner;
/**
* 加油站问题
*
* 这不能用背包来做,因为情况非常复杂
* 因为到每个加油站的状态并不是固定,因为不是每次都到加油不是把油正好加到下一个加油站
* 所以我们采用贪心的做法
* 情况如下:
* 1.刚开始,我们的车没油,所以要找0距离油价最少的那一个
* 2.然后考察车的最大距离里的所有加油站,看看是否有比当前油价少的加油站
* 1.若有,我们只需加油加到正好到该加油站即可,因为之后的距离我想用便宜的油价
* 2.若没有,我们只能在找到最大距离内大于当前油价最小的那一个即可,但是此时我们要
* 把油加满,因为当前油价便宜啊,加满之后,到大于当前油价最小的那一个的加油站时,继续考察
* 到的那个加油站即可。之后我们要再次根据距离,补充油(注意此时油箱是有油的,上次油价便宜)。
*
* 以上在油价时,我们用leftdis表示油箱中剩余的油能走的距离,所以在根据距离算钱,要减去该距离
* @author special
* @date 2018年1月29日 上午11:40:18
*/
public class Pro152 {
static double Cmax, D, Davg, onceMaxDis;
static int N;
static final double MIN = Double.MAX_VALUE;
static class Node{
double price;
double dis;
public Node(double price, double dis){
this.price = price;
this.dis = dis;
}
}
private static boolean less(Node node1, Node node2){
if(node1.dis < node2.dis || node1.dis == node2.dis
&& node1.price < node2.price){
return true;
}
return false;
}
public static void insertSort(Node[] nodes, int n){
for(int i = 1; i < n; i++){
for(int j = i; j > 0 && less(nodes[j], nodes[j - 1]); j--){
Node temp = nodes[j];
nodes[j] = nodes[j - 1];
nodes[j - 1] = temp;
}
}
}
public static void solution(Node[] nodes){
boolean flag = true;
int index = 0;
double nowPerPrice, nowDis = 0, maxDis, totalPrice = 0,
leftDis = 0, minPrice = MIN, minDis = 0;
while(nodes[index].dis == 0){ //找0距离的最小的油价的加油站
minPrice = Math.min(minPrice, nodes[index].price);
index++;
}
if(index == 0){ //若没有,说明没法走
flag = false;
}else{
nowPerPrice = minPrice; //更新当前的油价
boolean isShorter = false; //是否存在比当前油价小的加油站
while(nowDis < D){
maxDis = nowDis + onceMaxDis; //当前能到的最大位置
minPrice = MIN;
minDis = 0;
isShorter = false;
for(int i = index; i <= N && nodes[i].dis <= maxDis; i++){
if(nodes[i].dis == nowDis) continue;
if(nodes[i].price < nowPerPrice){ //因为我们排序的缘故,保证了大于当前位置的第一个加油站必是同位置的最小的
totalPrice += nowPerPrice * (nodes[i].dis - nowDis - leftDis) / Davg; //注意要减去油箱中剩余的油
nowPerPrice = nodes[i].price;
nowDis = nodes[i].dis;
leftDis = 0;
isShorter = true;
index = i;
break; //直接跳出即可,同位置之后的油价肯定是大于等于当前的
}
if(nodes[i].price < minPrice){ //我们还要记录最大距离的最小的油价,万一我们找不到更实惠,就可以将就一下
minPrice = nodes[i].price;
minDis = nodes[i].dis;
index = i;
}
}
if(!isShorter){ // 真没有比当前更实惠的
if(minPrice == MIN){ //油价还是天价,说明我们的车不行,跑不到加油站
nowDis += onceMaxDis; //在当前的加油站,加满,跑完得了,因为车不行
flag = false;
break;
}else{
totalPrice += nowPerPrice * (onceMaxDis - leftDis) / Davg; //否则就是我们加满油,跑到还可以接受的加油站
leftDis = onceMaxDis - (minDis - nowDis); //跑到那里之后,我们会剩余多少油
nowDis = minDis;
nowPerPrice = minPrice;
}
}
}
}
if(flag){
System.out.format("%.2f\n", totalPrice);
}else{
System.out.format("The maximum travel distance = %.2f\n", nowDis);
}
}
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while(input.hasNext()){
Cmax = input.nextDouble();
D = input.nextDouble();
Davg = input.nextDouble();
N = input.nextInt();
Node[] nodes = new Node[N + 1];
onceMaxDis = Cmax * Davg; //油箱满的时候,走的最大距离
for(int i = 0; i < N; i++){
nodes[i] = new Node(input.nextDouble(), input.nextDouble());
}
nodes[N] = new Node(0, D);
insertSort(nodes, N + 1); // 插入排序,为了减少内循环的次数
solution(nodes);
}
}
}
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; struct station{ double pi; int di; }; bool cmp(station a,station b){ return a.pi>b.pi; } int main(){ int cmax,d,davg,n,i,j; cin>>cmax>>d>>davg>>n; double money[d],sum=0,dist; station sta[n]; for(i=0;i<n;i++)cin>>sta[i].pi>>sta[i].di; sort(sta,sta+n,cmp); for(j=0;j<d;j++)money[j]=-1; for(i=0;i<n;i++){ for(j=sta[i].di;j<sta[i].di+cmax*davg&&j<d;j++){ money[j]=sta[i].pi/davg; } } for(j=0;j<d;j++){ if(money[j]==-1)break; sum+=money[j]; } if(j==d)printf("%.2f\n",sum); else { dist=(double)j; printf("The maximum travel distance = %.2f\n",dist); } return 0; }
#include <iostream> #include <algorithm> #include <iomanip> using namespace std; struct gasT{ double price; int pos; }; bool compareByPos(gasT a,gasT b){ if(a.pos==b.pos){ return a.price<b.price;//位置相同以油价升序排列 }else{ return a.pos<b.pos;//以位置升序排列 } } int main() { int capacity, TotalDistance, DistancePerGas, GasTnum; while (cin >> capacity >> TotalDistance >> DistancePerGas >> GasTnum) { gasT pos[GasTnum+1]; for (int i = 0; i < GasTnum; ++i) { cin >> pos[i].price >> pos[i].pos; } sort(pos, pos + GasTnum, compareByPos); pos[GasTnum].price=0;//把终点设为加油站 pos[GasTnum].pos=TotalDistance; //贪心思路:每到一个加油站向后查询一个满油能跑距离内是否有比目前油价便宜的最近加油站(加油至足够到达该目的加油站 //结束条件:终点距离加油站满油距离内,距离内部的加油站价格都比目前高,加油至终点,结束查询,输出消费 int fullGasRun = capacity * DistancePerGas;//满油能跑的距离 double leftRun = 0;//还能跑多远 double spend = 0;//目前消费 double run = 0;//目前走了多远 int t = 0;//目前到的加油站-1(以距离起点位置升序排号) while(t<GasTnum+1){ if(pos[0].pos!=0){//起点没有加油站,退出输出 cout << "The maximum travel distance = " << 0.00 << endl; break; } int cheap=0; for(int j=t+1;pos[j].pos-pos[t].pos<=fullGasRun;j++){//1.位置要在满油距离内//在目前的加油站向后遍 if(pos[t].price >= pos[j].price){//2.找比目前便宜的第一个加油站(一样价格也可以) if(leftRun<pos[j].pos - pos[t].pos){//余油不足,把油加到刚好够到达便宜加油站的量即可 spend = (pos[j].pos - pos[t].pos - leftRun)* pos[t].price /DistancePerGas+spend; leftRun = pos[j].pos - pos[t].pos; } run += pos[j].pos - pos[t].pos;//余油充足与否都需要的操作 leftRun = leftRun -pos[j].pos + pos[t].pos; t=j; cheap=1; break;//退出for的小循环 } } if(leftRun+pos[t].pos>=TotalDistance){//可到达终点,输出 cout << fixed << setprecision(2) << spend << endl; break; } if(cheap==0){//没有便宜的加满 spend += (fullGasRun - leftRun) / DistancePerGas * pos[t].price; leftRun = fullGasRun; }else{ continue;//找到便宜的加油站就不执行下面的操作 } if(pos[t+1].pos-pos[t].pos>fullGasRun){//下一个油站不在满油距离内(把leftrun清空) run+=leftRun; cout<< fixed << setprecision(2) << "The maximum travel distance = "<< run << endl; break; } t++;//走到下一个加油站 leftRun-= pos[t].pos-pos[t-1].pos; run+=pos[t].pos-pos[t-1].pos; } } }
#include <iostream> #include <algorithm> #include <iomanip> #include <vector> using namespace std; using pdi = pair<double, int>; const int N = 510; double c, d, s; // capacity, distance, dis per gas, stations int n; int main() { while (cin >> c >> d >> s >> n) { vector<pdi> ps(n); for (int i = 0; i < n; i++) { cin >> ps[i].first >> ps[i].second; } sort(ps.begin(), ps.end(), [](pdi p1, pdi p2) { return p1.second < p2.second; }); double price = 0.0; double dis = 0; auto current = ps.begin(); double capa = 0; while (current != ps.end()) { auto ith = find_if(current + 1, ps.end(), [&](pdi p) { // false 表示找不到性价比高的或者开不到性价比高的那一站 double max_dis = current->second + c * s; if (p.second > max_dis) { return false; } if (p.first <= current->first) { return true; } else { return false; } }); if (ith == ps.end()) { // 找不到h double max_dis = current->second + c * s; auto next = current + 1; if (max_dis < next->second) { // 开不到下一站 cout << "The maximum travel distance = " << fixed << setprecision(2) << max_dis << endl; break; } else if (max_dis >= d) { // 能直接开往终点 price += (d - current->second - capa * s) / s * current->first; cout << fixed << setprecision(2) << price << endl; break; } else { // 不能开往终点, 加满油, 开到下一站 price += (c - capa) * current->first; capa = c - (next->second - current->second) / s; current = next; } } else { // 找到h, 加油至h double cd = current->second + capa * s; if (cd >= ith->second) { // 油够用 capa -= (ith->second - current->second) / s; current = ith; } else { // 油不够, 加油加到刚好能到ith price += ((ith->second - capa * s - current->second) / s) * current->first; capa = 0.0; current = ith; } } if (current == ps.end() - 1) { double max_dis = current->second + c * s; if (max_dis >= d) { price += (d - current->second - capa * s) / s * current->first; cout << fixed << setprecision(2) << price << endl; break; } else { cout << "The maximum travel distance = " << fixed << setprecision(2) << max_dis << endl; break; } } } } }