当前位置:首页 > 入门组 > 【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

4个月前 (07-04)

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释) NOIP普及组  动态规划 C++代码 第1张

一、题目解读

题目要求解决旅行家从起点到终点(D1公里)的预算问题,需在沿途N个加油站中规划加油策略,使总费用最小化。每个加油站有不同油价和距离,汽车每升油可行驶D2公里,初始油量为C升,终点无加油站。需在满足油量限制的条件下,找到最经济的加油方案。

二、解题思路

核心思路为动态规划结合贪心算法。通过以下关键点实现:

1. 虚拟终点:将终点视为价格为零的虚拟加油站,确保算法完整性。

2. 距离排序:按距离对加油站排序,便于按顺序遍历。

3. 贪心选择:每次优先选择当前可达范围内最便宜的加油站,避免回溯。

4. 油量管理:实时计算当前油量能否到达下一站,按需加油至恰好可到达最远点。

三、解题步骤

1. 数据输入:读取起点距离D1、初始油量C、终点距离D2、初始油价P及N个加油站信息。

2. 构造虚拟终点:添加距离为D1、油价为0的虚拟终点站。

3. 排序加油站:按距离升序排序,确保遍历顺序正确。

4. 初始化变量:记录当前油量、总费用、当前位置。

5. 核心循环:

    寻找当前可达范围内最便宜的加油站(贪心)。

    计算到达该站所需油量,若当前油量不足则补充。

    更新总费用与位置,直至到达终点。

6. 边界判断:若无法到达第一个加油站,直接输出无解。

四、代码与注释

#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 = max_distance;  // 补满油  
            } else {  
                current_gas -= needed_gas;  // 否则消耗油量  
            }  
            current_station = cheapest_station;  // 更新位置  
        } else {  // 若找不到更便宜的站,直接前往终点  
            total_cost += (D1 - stations[current_station].distance) / D2 * stations[current_station].price;  
            break;  
        }  
    }  

    cout << fixed << setprecision(2) << total_cost << endl;  // 输出结果  
    return 0;  
}

五、总结

本解法通过动态规划思想,将问题转化为“在固定顺序下选择最优加油站”的贪心问题,避免了复杂的回溯。关键点在于:

1. 利用虚拟终点简化边界处理;

2. 排序后顺序遍历降低时间复杂度;

3. 实时计算油量差,避免冗余加油。

该算法时间复杂度为O(NlogN)(排序),空间复杂度O(N),适用于中小规模数据。


原创内容 转载请注明出处

分享给朋友:

相关文章

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

一、题目解读小杨买饮料是GESP 2023年六级认证考试中的一道经典动态规划题目,考察学生对背包问题的理解和应用能力。题目描述小杨需要购买n种饮料,每种饮料有特定的体积w和价格v,他要在不超过容量l的...

【蓝桥杯2015省赛解析】生命之树:树形DP解题全攻略(洛谷P8625代码详解)

【蓝桥杯2015省赛解析】生命之树:树形DP解题全攻略(洛谷P8625代码详解)

一、题目解读    “生命之树”是一道经典的树形结构问题,要求计算一棵带权树中,以某个节点为根的最大子树权值和。题目输入为n个节点及边信息,每个节点有权值wi,...

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

一、题目解读洛谷2789题要求计算n条直线在平面上两两相交时产生的不同交点数量。题目强调“不同”交点,需排除重复情况。解题关键在于如何高效枚举所有可能的交点组合,并避免重复计数。二、解题思路参考代码采...

洛谷P4999题解析:动态规划求解数字拆分与求和问题(附代码)

洛谷P4999题解析:动态规划求解数字拆分与求和问题(附代码)

一、题目解读洛谷P4999题要求处理给定区间 [L, R] 内数字的拆分与求和问题。每个数字需拆分为其各位数字之和,并计算区间内所有数字之和的累加结果。题目需考虑大数情况,并采用取模运算(MOD=1e...

力扣931题最小下降路径和解析 动态规划解法 LeetCode解题技巧

力扣931题最小下降路径和解析 动态规划解法 LeetCode解题技巧

一、题目解读力扣931题「Minimum Falling Path Sum」(最小下降路径和)要求在一个n x n的整数矩阵中,计算从顶部到底部的最小路径和。路径只能从每个位置向下或对角线移动(即向下...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。