找回密码
 立即注册
查看: 37|回复: 0

2021年CSP-S廊桥分配(洛谷P7913):贪心算法与优先队列实战

[复制链接]
  • 打卡等级:即来则安
  • 打卡总天数:28
  • 打卡月天数:2
  • 打卡总奖励:194
  • 最近打卡:2025-08-15 15:43:34

36

主题

2

回帖

2544

积分

VIP会员

积分
2544
发表于 2025-7-17 16:32:12 | 显示全部楼层 |阅读模式


一、问题背景分析
2021年CSP-S竞赛的廊桥分配问题要求优化分配有限廊桥资源,**化服务国内和国际航班数量。题目核心是处理两类航班的起降时间冲突,通过动态调度实现资源高效利用。
二、核心算法设计1. 数据结构选择// 优先队列存储可用廊桥编号(按编号排序)priority_queue<int, vector<int>, greater<int>> available;// 优先队列存储使用中廊桥的释放时间和编号(按时间排序)priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> in_use;2. 航班处理流程
  • 时间排序:所有航班按到达时间升序排列
  • 资源释放:检查并回收已完成服务的廊桥
  • 资源分配

    • 优先分配已释放的廊桥
    • 若无可用则分配新廊桥(不超过上限)

while (!in_use.empty() && in_use.top().first <= arrive) {    available.push(in_use.top().second);    in_use.pop();}3. 动态统计结果
通过前缀和数组记录不同廊桥数量下的服务能力:
vector<int> res(max_bridges + 1, 0);//...分配时更新对应廊桥计数if (bridge <= max_bridges) {    res[bridge]++;}//...**计算前缀和for (int i = 1; i <= max_bridges; ++i) {    res += res[i - 1];}三、完整代码解析
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <queue>
  5. using namespace std;

  6. // 计算使用k个廊桥时能服务的**航班数
  7. vector<int> calculate_max_flights(const vector<pair<int, int>>& flights, int max_bridges) {
  8.     vector<int> res(max_bridges + 1, 0);
  9.     if (flights.empty()) return res;
  10.    
  11.     // 按到达时间排序航班
  12.     vector<pair<int, int>> sorted_flights = flights;
  13.     sort(sorted_flights.begin(), sorted_flights.end());
  14.    
  15.     // 优先队列存储可用廊桥的释放时间
  16.     priority_queue<int, vector<int>, greater<int>> available;
  17.     // 优先队列存储正在使用的廊桥的释放时间
  18.     priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> in_use;
  19.    
  20.     int count = 0;
  21.     for (const auto& flight : sorted_flights) {
  22.         int arrive = flight.first;
  23.         int depart = flight.second;
  24.         
  25.         // 释放已经完成的廊桥
  26.         while (!in_use.empty() && in_use.top().first <= arrive) {
  27.             available.push(in_use.top().second);
  28.             in_use.pop();
  29.         }
  30.         
  31.         // 如果有可用廊桥,则分配
  32.         if (!available.empty()) {
  33.             int bridge = available.top();
  34.             available.pop();
  35.             in_use.push({depart, bridge});
  36.             count++;
  37.             if (bridge <= max_bridges) {
  38.                 res[bridge]++;
  39.             }
  40.         }
  41.         // 如果没有可用廊桥但还有未分配的廊桥,则分配新的
  42.         else if (in_use.size() < max_bridges) {
  43.             int bridge = in_use.size() + 1;
  44.             in_use.push({depart, bridge});
  45.             count++;
  46.             if (bridge <= max_bridges) {
  47.                 res[bridge]++;
  48.             }
  49.         }
  50.     }
  51.    
  52.     // 计算前缀和
  53.     for (int i = 1; i <= max_bridges; ++i) {
  54.         res[i] += res[i - 1];
  55.     }
  56.    
  57.     return res;
  58. }

  59. int main() {
  60.     ios::sync_with_stdio(false);
  61.     cin.tie(nullptr);
  62.    
  63.     int n, m1, m2;
  64.     cin >> n >> m1 >> m2;
  65.    
  66.     vector<pair<int, int>> domestic(m1), international(m2);
  67.     for (int i = 0; i < m1; ++i) {
  68.         cin >> domestic[i].first >> domestic[i].second;
  69.     }
  70.     for (int i = 0; i < m2; ++i) {
  71.         cin >> international[i].first >> international[i].second;
  72.     }
  73.    
  74.     // 计算国内和国际航班在不同廊桥数量下的**服务数
  75.     auto domestic_res = calculate_max_flights(domestic, n);
  76.     auto international_res = calculate_max_flights(international, n);
  77.    
  78.     // 寻找**分配方案
  79.     int max_total = 0;
  80.     for (int i = 0; i <= n; ++i) {
  81.         int j = n - i;
  82.         if (i < 0 || j < 0) continue;
  83.         int total = domestic_res[i] + international_res[j];
  84.         if (total > max_total) {
  85.             max_total = total;
  86.         }
  87.     }
  88.    
  89.     cout << max_total << endl;
  90.    
  91.     return 0;
  92. }
复制代码
来源:竞赛学习

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表