1999年NOIP普及组旅行家的预算(洛谷P1016):贪心算法实战指南

截图未命名.jpg 1999年NOIP普及组旅行家的预算(洛谷P1016):贪心算法实战指南 NOIP 算法竞赛 贪心算法 C++ 普及组 洛谷题解 第1张

一、问题背景

旅行家的预算是NOIP1999普及组的经典题目,考察贪心算法在实际问题中的应用。题目描述一位旅行家需要从起点到终点,途中有若干个加油站,每个加油站油价不同,要求在有限油箱容量下规划最优加油策略,使总花费最少。

二、数据结构设计

arduino 复制代码
struct Station {
    double distance;  // 加油站距离起点的位置
    double price;     // 该加油站的油价
};

使用结构体存储每个加油站的信息,便于后续处理。

三、核心算法思路

  1. 加油站预处理 :将起点和终点也视为特殊加油站,并按距离排序
  2. 可达性检查:计算满油能行驶的最大距离(C*D2)
  3. 贪心策略:
    • 优先寻找当前可达范围内比当前站更便宜的加油站
    • 若无更便宜加油站,则在当前站加满油
    • 每次只加到达下一站所需的油量

四、完整代码解析

C++ 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;

struct Station {
    double distance;
    double price;
};

int main() {
    double D1, C, D2, P;
    int N;
    cin >> D1 >> C >> D2 >> P >> N;
    
    vector<Station> stations(N+2);
    stations[0] = {0, P}; // 起点加油站
    for (int i = 1; i <= N; ++i) {
        cin >> stations[i].distance >> stations[i].price;
    }
    stations[N+1] = {D1, 0}; // 终点设为虚拟加油站
    
    // 按距离排序加油站
    sort(stations.begin(), stations.end(), [](const Station& a, const Station& b) {
        return a.distance < b.distance;
    });
    
    double max_distance = C * D2; // 满油能行驶的最大距离
    double current_gas = 0; // 当前油量
    double total_cost = 0; // 总花费
    int current_station = 0; // 当前所在加油站
    
    // 检查是否能到达第一个加油站
    if (stations[1].distance > max_distance) {
        cout << "No Solution" << endl;
        return 0;
    }
    
    while (current_station <= N) {
        // 寻找下一个比当前便宜的加油站
        int next_station = current_station + 1;
        double min_price = stations[current_station].price;
        int cheapest_station = -1;
        
        // 在可达范围内寻找最便宜的加油站
        while (next_station <= N+1 && 
               stations[next_station].distance - stations[current_station].distance <= max_distance) {
            if (stations[next_station].price < min_price) {
                min_price = stations[next_station].price;
                cheapest_station = next_station;
                break; // 找到第一个更便宜的加油站就停止
            }
            next_station++;
        }
        
        if (cheapest_station != -1) {
            // 计算需要加的油量
            double distance = stations[cheapest_station].distance - stations[current_station].distance;
            double needed_gas = distance / D2 - current_gas;
            if (needed_gas > 0) {
                total_cost += needed_gas * stations[current_station].price;
                current_gas = 0;
            } else {
                current_gas -= distance / D2;
            }
            current_station = cheapest_station;
        } else {
            // 没有更便宜的加油站,加满油到最远的加油站
            if (stations[current_station].distance + max_distance >= D1) {
                // 可以直接到达终点
                double distance = D1 - stations[current_station].distance;
                double needed_gas = distance / D2 - current_gas;
                if (needed_gas > 0) {
                    total_cost += needed_gas * stations[current_station].price;
                }
                cout << fixed << setprecision(2) << total_cost << endl;
                return 0;
            }
            
            // 检查是否能到达下一个加油站
            next_station = current_station + 1;
            if (next_station > N || 
                stations[next_station].distance - stations[current_station].distance > max_distance) {
                cout << "No Solution" << endl;
                return 0;
            }
            
            // 加满油到下一个加油站
            total_cost += (C - current_gas) * stations[current_station].price;
            current_gas = C - (stations[next_station].distance - stations[current_station].distance) / D2;
            current_station = next_station;
        }
    }
    
    cout << fixed << setprecision(2) << total_cost << endl;
    return 0;
}

五、常见错误与优化

  1. 可达性检查:必须首先检查能否到达第一个加油站
  2. 浮点数精度:使用double类型并控制输出精度
  3. 边界条件:特别注意终点处理和无解情况

转自:1999年NOIP普及组旅行家的预算(洛谷P1016):贪心算法实战指南

相关推荐
坤坤子吖2 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
一晌小贪欢3 小时前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
xiaoye-duck3 小时前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
一条大祥脚4 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·4 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
旖旎夜光4 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
青少儿编程课堂6 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青7 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
旖旎夜光8 小时前
【C++ 基础入门】C++ 继承(上):概念、切片、隐藏、默认成员函数与友元
c++·笔记·学习
apcipot_rain8 小时前
C++转Java日记(05)
java·开发语言·c++