1033 To Fill or Not to Fill

一、原题链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805458722734080

二、题面

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

三、输入

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.

四、输出

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.思路需要通过样例数据验证
2.全局都是double(直接尽量开double避免麻烦)
3.注意边界(本例中左边界是可测的)

注:测试点四一直没通过,通过网上的一个样例找到了bug

六、code

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f

//最后一次的油可能超了

using namespace std;

typedef struct{
    double price;
    double dist;
}Node;

const int N=1e3+10;

Node arr[N];

double min(double a,double b){
    return a<b?a:b;
}

double max(double a,double b){
    return a>b?a:b;
}

bool cmp(Node arr1,Node arr2){
    if(arr1.dist!=arr2.dist){
        return arr1.dist < arr2.dist;
    }else{
        return arr1.price < arr2.price;
    }
}

double e;
int c,s,n;

int main(){
    cin >> c >> s >> e >>n; //efficiency
    for(int i=0;i<n;i++){
        cin >> arr[i].price >> arr[i].dist;
    }
    sort(arr,arr+n,cmp);
    double res=0,dist=0,carry=0;  //res描述cheapst price,dist描述所走的距离,carry描述当前携带的油
    //每次到达
    for(int i=0;i<n;i++){
        //cout << "i:" << i << " dist:" << dist << " carry:" << carry << endl;
        double usage=(arr[i].dist-dist)/e;  //耗油
        if(usage>carry){
            dist+=carry*e;
            printf("The maximum travel distance = %.2lf\n",dist);
            return 0;
        }
        carry-=usage;
        dist=arr[i].dist;
        //cout << "i:" << i << " dist:" << dist << " carry:" << carry << endl;
        //cout << "dist:" << dist << " carry:" << carry << endl;
        double need=0;  //需要加的油量
        if(dist==arr[i].dist){
            //对当前油量的处理
            //考虑加多少油
            double farthest=min(dist+c*e,s);
            //cout << "farthest:" << farthest << endl;
            int temp=i;  //temp可能越界
            for(int j=i+1;j<n;j++){
                //cout << "j:" << j << endl;
                if(arr[j].dist<=farthest&&arr[j].price<arr[temp].price){
                    temp=j;
                    break;  //第一个比当前便宜的
                }
            }
            //cout << "temp:" << temp << endl;
            if(i!=n-1){
                if(temp!=i){
                    //cout << "carry:" << carry << " arr[temp].dist:" << arr[temp].dist << " dist:" << dist << endl;
                    need=max((arr[temp].dist-dist)/e-carry,0);
                    //cout << "need1:" << need << endl;
                }else{  //尽可能多加油,但是不能越上界
                    need=c-carry;
                    if((need+carry)*e>s-dist){  //如果加油超界
                        need=(s-dist-carry*e)/e;
                    }
                    //cout << "need2:" << need << endl;
                }
            }else{
                //能到终点的情况下没有和当前油箱比较
                need=min((s-dist)/e-carry,c-carry);  //或者携带到最大
                //cout << (s-dist)/e << " " << c-carry << endl;
                //cout << "need3:" << need << endl;
            }
        }
        //cout << "i:" << i << " need:" << need << endl;
        res+=arr[i].price*need;
        carry+=need;
    }
    //cout << dist << " " << carry << endl;
    //cout << "dist:" << dist+carry*e << endl;
    //cout << "res:" << res << endl;
    if(dist+carry*e==s||dist==0){  //特判一个左边界0的位置
        printf("%.2lf\n",res);
    }else{
        printf("The maximum travel distance = %.2lf\n",dist+carry*e);
    }
    return 0;
}

//样例无通不过去:没有考虑到c极大的情况

//测试点4
/*
data
50 1300 12 8
7.10 0 
7.00 150 
7.50 400 
8.00 600 
7.20 900 
7.30 1000 
6.00 1250 
6.85 1280

correct answer:767.50 
*/
posted @ 2022-01-16 14:09  Arno_vc  阅读(31)  评论(0编辑  收藏  举报