贪心算法——旅行家的预算(NOIP1999)

问题描述:
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(0 <= N <= 100),油站i离出发点的距离Di、每升汽油价格Pi(i=1,2,……N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No solution”。

输入
 第一行为4个实数D1、C、D2、P与一个非负整数N;
 接下来N行,每行两个实数Di、Pi

输出
如果可以到达目的地,输出一个实数(四舍五入至小数点后两位),表示最小费用;否则输出“No Solution”(不含引号)。

样例输入

275.6 11.9 27.4 2.8 2
102.0 2.9
220.0 2.2

【样例输出】

26.95

策略分析:

旅行家的预算问题,需要想清楚情况才能做,首先要总的消费小,我们每次加油都需要考虑油价尽可能便宜的加油站加油,那么需要在当前的位置下,假如加满油,看看能经过多少个加油站,然后进行判断,那么可以分成两种情况来做

1、在当前加满油后能到达的所有加油站中比较油价,假如当前位置的油价最低,那么一定要加满油,然后开到下一个加油站在再次进行比较选择

2、在当前加满油后能到达的所有加油站中比较油价,假如出现了更便宜的加油站,那么只需要加的油够刚好到达那一个加油站即可

反复判断这两种情况,这样的选择才能保证是最优的
由于注释写的很清楚,就不过多赘述

代码

#include <cstdio>
#include <algorithm>
#define MAXN 105
using namespace std;
struct oil {
    double d, p;
}a[MAXN];
bool cmp(oil x, oil y) {
	return x.d <= y.d;
} 
double D1, C, D2, P;//分别表示总距离D1,容量C,每升油行驶距离D2,出发点价格P 
double dis, loc, ca, cost, reach, mn;
//分别表示加满油能跑的距离dis,当前位置loc,油箱中油量ca,花费的钱cost, reach表示加满油能到的位置 
// 把P表示成当前油价,每次更新即可 
int i = 1, t, n; 
bool flag;
int main() {
    scanf("%lf%lf%lf%lf%d", &D1, &C, &D2, &P, &n); 
    dis = C * D2;
    for(i = 1; i <= n; i++)
        scanf("%lf%lf", &a[i].d, &a[i].p);
    a[0].d = 0;
    for(i = 1; i <= n; i++)
        if(a[i].d - a[i-1].d > dis) {
            printf("No Solution\n");
            return 0;
        }
    sort(a, a+n+1, cmp);
    i = 0;
    while(loc < D1) {
        flag = 0;
        reach = loc + dis;  //表示当前能到达的最远距离 
        for(int j = i+1; j <= n && a[j].d <= reach; j++) { //找出比当前加油站油价更便宜的下一个加油站 
            if(a[j].p < P) {
                flag = 1;
                t = j;
                break; 
            }
        }
        if(!flag) {//如果在能到达的范围没有找到 , 那么寻在当前地方加满油,直接开到下一个加油站再次反复寻找 
            if(reach >= D1) { //如果当前最便宜的状态下加满油能够到达终点 
                if((D1-loc) / D2 > ca) //如果当前油箱的油不够 ,加到刚好到终点退出 
                    cost += ((D1-loc) / D2 - ca) * P;
                break;
            }
			t = i + 1; //开到下一个加油站 
            cost += (C-ca) * P;  //将油加满 
            ca = C - (a[t].d - loc) / D2; //减去到达下一个点耗费的油 
            loc = a[t].d; //更新 
            P = a[t].p;
            i = t;
        }else { //去到比当前便宜的下一个站  flag == 1
            if((a[t].d - loc) / D2 > ca) { //如果油不够则加到刚好到达下一个为止 
                cost += ((a[t].d - loc) / D2 - ca) * P;
                ca = 0;
            }else   //如果油够则直接减去损耗的油 
                ca -= (a[t].d - loc) / D2;
     
            loc = a[t].d;  //更新 
            P = a[t].p;
            i = t;
        }
    } 
    printf("%.2lf\n", cost);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43501684/article/details/89057658