您的位置:首页 > 其它

PAT To Fill or Not to Fill

2018-01-23 22:10 169 查看
链接:https://www.nowcoder.com/questionTerminal/4ad3d8cde8ca4889a32ed0a89edeefeb
来源:牛客网

[编程题]To Fill or Not to Fill (25)热度指数:666时间限制:1秒空间限制:65536K
算法知识视频讲解
With highways available, driving a car from Hangzhou to any other cityis easy. But since the tank capacity of a car is limited, we have tofind gas stations on the way from time to time. Different gas stationmay give different price. You are asked to carefully design thecheapest route to go.
[b]输入描述:[/b]
Each input file contains one test case.  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.


[b]输出描述:[/b]
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.
示例1

输入

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

输出

749.17
//#include"stdafx.h"
#include"stdio.h"
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<vector>
#include<deque>
#include<math.h>
using namespace std;
double cmax,dis;
int n;
double per;
struct node{
double p;
double d;
node(double p,double d):p(p),d(d){}
};
vector<node>vec;
double ans=0;
double price,d;

bool cmp(node a,node b){return a.d<b.d;
}

void cal(int in,double tank){//tank refer to how much gasoline remaining;

double cm=min(1.0*cmax,(dis-vec[in].d)/per);//maybe it's not necceessary to fill your tank,because the //destination is not so far;
double far=cmax*per;//if full,the farest distance to go
if((in+1<vec.size()&&vec[in+1].d-vec[in].d>far)||in+1>=vec.size()){if(vec[in].d+far<dis){
//when you can not reach the destination,maybe because there is no next station or the next sation is beyond the //farest

cout<<"The maximum travel distance = ";
printf("%.2f",vec[in].d+far);
}
else {
ans+=((dis-vec[in].d)/per-tank)*vec[in].p;
printf("%.2f\n",ans);}

}

else {int i,flag=0;double minp=vec[in+1].p,sel=in+1;
for(i=in+1;i<vec.size()&&vec[i].d<=vec[in].d+far;i++)
{if(vec[in].p>=vec[i].p){ans+=vec[in].p*((vec[i].d-vec[in].d)/per-tank);
cal(i,0);flag=1;break;//if there is an accessable station whose price is lower than the current //one's
}
if(minp>vec[i].p){sel=i;minp=vec[i].p;}//at the same time,make notes of the station with the lowest price
}
if(flag==0){

ans+=vec[in].p*(cm-tank);//if all the available stations offer gasoline at a price higher,try to //get to the lowest one
cal(sel,cm-(vec[sel].d-vec[in].d)/per);//fill as possible as you can
}	}}

int main(){
// freopen("c://jin.txt","r",stdin);
cin>>cmax>>dis>>per>>n;
while(n--){
cin>>price>>d;
vec.push_back(node(price,d));
}
sort(vec.begin(),vec.end(),cmp);
cal(0,0);
//freopen("CON","r",stdin);
// system("pause");

return 0;
}
2018.3.7重刷了这道题,再次总结一下思路
需要的注意的地方
1.对加油站按距离排序
2.相同位置的加油站可能有多个,注意去掉重复,保留相同位置价格最低的加油站,将有利于计算
3.计算相邻加油站的之间的距离,如果超过满油箱能行驶的范围,一定达不到终点
4.在顺序枚举加油站时,采用贪心算法
如果下一站的油比这一站的便宜,油箱里只需要够到达下一站的油
否则,油箱里应该存够到最近的更便宜的加油站所需要的油,并开往下一站。
在这里有可能后面没有更便宜的加油站了,并且终点站在满油箱的距离内,那就加到够终点站的油,否则,在这一站加满油
如果在满油箱距离内都没有更便宜的加油站了,那就加满油
//#include "stdafx.h"
#include"stdio.h"
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=550;
const int inf=0x7fffffff;
 
double cmax,dis,g;
int n;
double l;
double p,d;
struct node{
    double p;
    double d;
    double f;
node(double p,double d):p(p),d(d){}
};
vector<node>no;
double dp[maxn];
string s="The maximum travel distance = ";
bool cmp(node a,node b)
{
   if(a.d!=b.d) return a.d<b.d;
    else return a.p<b.p;
}
 
 
 
 
 
 
int main(){
 
 
 
    //freopen("c://jin.txt","r",stdin);
    while(cin>>cmax>>dis>>g){
        int flag=0;
        double far=0;
        cin>>n;
        l=cmax*g;
        for(int i=0;i<n;i++)
        {cin>>p>>d;
no.push_back(node(p,d));
}
sort(no.begin(),no.end(),cmp);
        for(int i=1;i<n;i++)
if(no[i].d==no[i-1].d){no.erase(no.begin()+i);n--;}

for(int i=0;i<n;i++)
{if(i!=n-1){no[i].f=no[i+1].d-no[i].d;

}
        else no[n-1].f=dis-no[n-1].d;
        if(no[i].f>l){flag=1;far=no[i].d+l;break;}
        }
        if(flag){cout<<s;printf("%.2f\n",far);}//前面都在计算两站间的距离是否超过加满油行驶的范围
        else{
 
            int i=0;double ans=0;//i表示现在到了哪一个加油站,ans表示当前花费的钱
            double w=0,need;//w表示当前剩下多少油,need表示现在需要加多少油
            while(i<n){
if(i==n-1){ans+=max(((dis-no[i].d)/g-w)*no[i].p,0.0);break;}//如果已经是最后一站了,只需要够到终点的油
    else if(no[i+1].p<=no[i].p){//如果下一站便宜
    need=no[i].f/g;
if(w>=need){w-=need;}
else{ans+=(need-w)*no[i].p;w=0;}
i++;
                }
              
else{ int j=1;
while(i+j<n&&no[i+j].d-no[i].d<=l&&no[i+j].p>no[i].p)j++;
if(i+j==n){//如果后面没有更便宜的了
if(dis-no[i].d<=l){ans+=max(((dis-no[i].d)/g-w)*no[i].p,0.0);break;}
else {ans+=(cmax-w)*no[i].p;
i++;
w=cmax-no[i].f/g;}
}
else if(no[i+j].d-no[i].d>l){//如果在最大距离内没有更便宜的了
    ans+=(cmax-w)*no[i].p;
w=cmax-no[i].f/g;
i++;

}
else{//i+j号加油站是比i号更便宜
need=(no[i+j].d-no[i].d)
cea8
/g;
if(w<need){ans+=(need-w)*no[i].p;w=need;}
      w-=no[i].f/g;
      i++;
}

}

}
 
            printf("%.2f\n",ans);
        }
 
 
    }
 
 
 
 
  //freopen("CON","r",stdin);
// system("pause");
 
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: