2021年CSP-S廊桥分配问题解析(洛谷P7913):基于贪心算法与优先级队列的解题思路

深度学习
• 阅读 9

2021年CSP-S廊桥分配问题解析(洛谷P7913):基于贪心算法与优先级队列的解题思路

一、题目解读

2021年CSP-S中的“廊桥分配”(洛谷P7913)是一个经典的资源分配问题。题目要求处理n个航班,每个航班有到达和离开时间,需在m1到m2个廊桥的限制下,计算使用不同数量的廊桥时能服务的最大航班数。核心在于高效分配廊桥资源,避免时间冲突,同时满足数量限制。

二、解题思路

采用贪心策略与优先级队列优化

  1. 航班排序:按到达时间升序排列,确保处理顺序符合时间逻辑。

  2. 动态分配:使用两个优先队列——available存储当前可用廊桥的释放时间,in_use存储正在使用的廊桥及释放时间。

  3. 分配逻辑:

    优先使用已释放的廊桥(时间不冲突时);

    若无可用廊桥且剩余廊桥数未满,新建分配。

  4. 前缀和优化:计算各廊桥数量的前缀和,便于快速查询不同k值下的最大服务数。

三、解题步骤

  1. 输入与预处理:读取航班数据,按到达时间排序。

  2. 初始化队列:available为空,in_use记录当前分配状态。

  3. 循环分配:

    释放过期廊桥(到达时间前已完成的航班);

    若available不空,分配最小释放时间的廊桥;

    否则若廊桥数未满,新建分配。

  4. 前缀和计算:累加各廊桥服务数,生成最终结果。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

// 计算使用k个廊桥时能服务的最大航班数
vector<int> calculate_max_flights(const vector<pair<int, int>>& flights, int max_bridges) {
    vector<int> res(max_bridges + 1, 0);
    if (flights.empty()) return res;

    // 按到达时间排序航班
    vector<pair<int, int>> sorted_flights = flights;
    sort(sorted_flights.begin(), sorted_flights.end());

    // 优先队列存储可用廊桥的释放时间
    priority_queue<int, vector<int>, greater<int>> available;
    // 优先队列存储正在使用的廊桥的释放时间
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> in_use;

    int count = 0;
    for (const auto& flight : sorted_flights) {
        int arrive = flight.first;
        int depart = flight.second;

        // 释放已经完成的廊桥
        while (!in_use.empty() && in_use.top().first <= arrive) {
            available.push(in_use.top().second);
            in_use.pop();
        }

        // 如果有可用廊桥,则分配
        if (!available.empty()) {
            int bridge = available.top();
            available.pop();
            in_use.push({depart, bridge});
            count++;
            if (bridge <= max_bridges) {
                res[bridge]++;
            }
        }
        // 如果没有可用廊桥但还有未分配的廊桥,则分配新的
        else if (in_use.size() < max_bridges) {
            int bridge = in_use.size() + 1;
            in_use.push({depart, bridge});
            count++;
            if (bridge <= max_bridges) {
                res[bridge]++;
            }
        }
    }

    // 计算前缀和
    for (int i = 1; i <= max_bridges; ++i) {
        res[i] += res[i - 1];
    }

    return res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m1, m2;
    cin >> n >> m1 >> m2;

    vector<pair<int, int>> domestic_flights(n);
    for (int i = 0; i < n; ++i) {
        cin >> domestic_flights[i].first >> domestic_flights[i].second;
    }
    vector<int> max_flights = calculate_max_flights(domestic_flights, m2);

    for (int i = m1; i <= m2; ++i) {
        cout << max_flights[i] << ';
    }
    cout << endl;

    return 0;
}

五、总结

算法通过优先级队列高效管理廊桥状态,结合贪心思想优先分配可用资源,避免回溯。前缀和的应用进一步简化了结果查询过程。时间复杂度为O(nlogn),适合处理大规模数据。关键点在于对资源释放时间的动态维护与分配优先级判断。

来源:2021年CSP-S廊桥分配问题解析(洛谷P7913):基于贪心算法与优先级队列的解题思路

点赞
收藏
评论区
推荐文章
贾蔷 贾蔷
4星期前
牛客12576题全解析:动态规划+质因数分解解决跳跃问题
一、题目解读牛客12576题是一道经典的算法题,要求给定起点N和终点M,求解从N到M的最少跳跃次数。题目考察的核心在于路径优化与动态规划思想,需结合数论中的质因数分解技巧,通过合理设计算法降低时间复杂度,避免暴力枚举的指数级耗时。二、解题思路采用“动态规划
贾蔷 贾蔷
4星期前
CSP-J 2019公交换乘题解析:基于队列优化的动态规划代码详解
一、题目解读CSPJ2019年的“公交换乘”题目(洛谷P5661)要求模拟地铁与公交交替出行的费用计算。题目核心在于地铁消费会产生优惠券,而公交可在45分钟内使用优惠券抵扣车费。需要处理n条出行记录,优化总费用。该问题考察对时间窗口与动态资源管理的理解,需
深度学习 深度学习
4星期前
【CSP-S 2019】括号树(洛谷P5658):栈+DFS
一、题目解读括号树问题(洛谷P5658)要求处理一个由括号序列转化的树结构:每个节点表示一个括号,'('为子节点,')'为父节点。题目给定一棵n个节点的树,需计算每个节点的深度(括号层数),并输出所有节点深度与节点编号乘积的异或和。核心在于将括号序列转化为
深度学习 深度学习
4星期前
洛谷1111题解:基于Kruskal算法与并查集的最小生成树实现
一、题目解读洛谷1111题是一道经典的图论问题,要求构建一个无向图的最小生成树,并输出其最大边权值。题目核心在于通过给定的边集合,找到连接所有节点的最小权值子集,同时保证无环。这通常涉及最小生成树算法(如Kruskal)的应用,需要高效处理边权重与节点连通
贾蔷 贾蔷
4星期前
2023年GESP六级题解:洛谷P10108闯关游戏动态规划解法详解
一、题目解读本文针对2023年GESP六级题目“闯关游戏”(洛谷P10108)进行详细解析。题目要求玩家通过不同关卡路径选择,计算从起点到终点的最大得分。关卡间存在跳跃规则,需结合动态规划思想设计高效算法,最终输出最优得分。二、解题思路采用动态规划(Dyn
深度学习 深度学习
4星期前
洛谷P2034题解:动态规划+单调队列优化求解最大K段子段和问题
一、题目解读洛谷P2034题目要求给定一个长度为n的整数数组,将其分成不超过k段,求各段和的最大值。该问题属于经典动态规划问题的扩展,需结合优化技巧高效求解。二、解题思路采用动态规划单调队列优化的策略。核心思想是定义状态dp
深度学习 深度学习
3星期前
2012年NOIP提高组「借教室」(洛谷P1083)解题思路与二分查找优化代码解析
一、题目解读本题为2012年NOIP提高组中的「借教室」问题(洛谷P1083),要求处理教室借用订单的分配问题。给定n天每天可用教室数量r和m个订单(订单包含需求教室数d、开始日期s、结束日期t),判断能否通过删除部分订单使所有订单满足教室容量限制。若能,
深度学习 深度学习
1星期前
2021年CSP-S廊桥分配(洛谷P7913):贪心算法与优先队列实战
一、问题背景分析2021年的廊桥分配问题要求分配有限廊桥资源,最大化服务国内和国际航班数量。题目核心是处理两类航班的起降时间冲突,通过动态调度实现资源高效利用。二、核心设计1.数据结构选择//优先队列存储可用廊桥编号(按编号排序)priorityqueue
贾蔷 贾蔷
1星期前
CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用
一、题目解读2019年的“纪念品”问题(对应P5662)要求玩家在T天内通过买卖纪念品最大化金币收益。每天可交易N种商品,需计算最优策略下的最终金币数。题目强调思维与资源分配优化,是中的经典题型。二、解题思路核心思路为“动态规划”。每天将当前商品价格与次
贾蔷 贾蔷
5天前
洛谷P1102题解:利用哈希表优化的数对统计 C++代码解析
一、题目解读P1102题要求处理一组整数与常数C,统计数组中是否存在元素A与B满足ABC。用户需输出满足条件的数对数量。题目关键在于快速判断是否存在互补元素,时间复杂度需优化以避免暴力遍历。二、解题思路采用(unorderedmap)实现高效统计。首先遍