PAT甲级1033 To Fill or Not to Fill (贪心算法)

原题链接

PAT甲级1033

题目大意

一辆车从杭州出发,前往目的地,途径若干个加油站,若能到达目的地,输出加油所花费的钱,若不能,输出能到达的最大距离。

解题思路

  1. 本题的核心思想就是尽量使用最便宜的油行驶。所以我们建立一个数组cheapSta[500],cheapSta[i]表示从加油站i出发在满油行驶距离之内的第一个比当前油站价格更低的站或者价格最低的油站。这个数组也代表了行驶线路。
  2. 建立递归函数Travel()。路线既然确定好了,那么我们需要判断汽车怎么加油。根据贪心算法的思想,汽车应尽量使用便宜的油。如果下一站cheapSta[cur_sta]的油价比当前站cur_sta更低,那么油量应使得汽车刚好开到cheapSta[i]站(油够用则不用加,否则将油加到刚好的量);如果下一站cheapSta[cur_sta]的油价比当前站更高,那么应该加满油。
  3. 注意:汽车开始时油箱没有油,若没有距离为0的加油站,直接输出最大距离0.00。

示例代码

#include<iostream>
#include<vector>
#include<algorithm>
#define MAX 2147483647;
using namespace std;

int Cmax, D, Davg, N;//油箱容量, 杭州到目的地的距离, 单位油行驶距离,加油站数量
int CD;//满油能跑的距离

int cheapSta[500];//汽车从车站i行驶满油距离所经过的最便宜的油站
bool canReach = true;
double res_dis, res_cost;

struct Station{
    double price, distance;
};
Station sta[501];//车站数组

bool disCompare(Station s1, Station s2){
    return s1.distance < s2.distance;
}

void Travel(int cur_sta, double cur_dis, double cur_oil, double cur_cost){
    int next_sta = cheapSta[cur_sta];

    //到达目的地
    if(cur_sta==N){
        res_dis = cur_dis;
        res_cost = cur_cost;
        return;
    }

    //若到下一个站的距离大于当前距离加满油距离,返回当前距离加满油距离
    if(next_sta<0){
        res_dis = cur_dis+CD;
        res_cost = cur_cost + Cmax*sta[cur_sta].price;
        canReach = false;
        return;
    }


    double dis = sta[next_sta].distance - cur_dis;//到下一车站的距离
    double oil = dis / Davg;//到下一车站的油量
    //若下一站的价格比当前站低,加油使得刚好开到下一站
    if(sta[next_sta].price < sta[cur_sta].price){
        //若当前油箱的油不够,花钱加油,否则不用
        if(cur_oil < oil){
            cur_cost += (oil - cur_oil) * sta[cur_sta].price;
            cur_oil  = oil;
        }
        Travel(next_sta, sta[next_sta].distance, cur_oil-oil, cur_cost);
    }else{//下一站的价格比当前站价格高,在当前站加满油过去
        cur_cost += (Cmax-cur_oil) * sta[cur_sta].price;
        Travel(next_sta, sta[next_sta].distance, Cmax-oil, cur_cost);
    }


}

int main(){
    cin >> Cmax >> D >> Davg >> N;
    CD = Cmax * Davg;
    for(int pos=0; pos<N; pos++){
        cin >> sta[pos].price >> sta[pos].distance;
    }
    sta[N].distance = D;
    sta[N].price = 0;
    sort(sta, sta+N+1, disCompare);//根据距离排序

    //起始位置没有加油站,直接输出最大距离0;
    if(sta[0].distance>0){
        cout << "The maximum travel distance = 0.00" << endl;
        return 0;
    }

    for(int cur_sta=0; cur_sta<N; cur_sta++){
        int CD_dis = sta[cur_sta].distance + CD;//cur_sta开始满油能跑到的距离
        int i = cur_sta + 1;
        double min_price = MAX;//最低油价
        int cheap_sta = -1;//最低油价的站,-1表示满油开不到
        while(sta[i].distance<=CD_dis && i<=N){
            if(sta[i].price<sta[cur_sta].price){//若找到第一个比当前站更低价格的油站,直接更新cheapSta
                min_price = sta[i].price;
                cheap_sta = i;
                break;
            }
            if(sta[i].price<min_price){
                min_price = sta[i].price;
                cheap_sta = i;
            }
            i++;
        }
        cheapSta[cur_sta] = cheap_sta;
        
    }


    Travel(0, 0, 0, 0);

    if(canReach){
        printf("%.2f", res_cost);
    }else{
        printf("The maximum travel distance = %.2f", res_dis);
    }

    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚风也很浪漫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值