1 条题解
-
0
「ROI 2024 Day1」飞行箱 题解
题目大意
有 个座位排成一排,坐标从 到 。餐车从坐标 出发,需要到达坐标 。有 种饮料,第 个座位的乘客需要饮料类型 。每瓶饮料可以装 份,餐车最多装 瓶。储藏室位置由 决定:
- :只在 处
- :只在 处
- :两端都有
求服务所有乘客的最短移动距离。
解题思路
关键观察
- 区间覆盖:每种饮料的需求可以看作若干区间,每个区间表示一瓶饮料服务的连续座位段
- 动态规划:用 表示服务完前 个座位的最小距离
- 贪心优化:使用优先队列维护最优转移
代码详解
数据结构定义
const int N = 1e6 + 5; int n, m, k, p, C, req[N], val[N]; vector<int> e[N], ed[N]; // 区间端点req[i]:第 个座位需要的饮料类型e[i]:以 为左端点的区间右端点ed[i]:以 为右端点的区间左端点val[i]:从位置 到最近储藏室的往返代价
预处理阶段
void Prepare() { static int tmp[N], curl[N]; for (int i = 1; i <= n; i++) { if (!tmp[req[i]]) { // 新开一瓶饮料 curl[req[i]] = i; // 记录区间起点 tmp[req[i]] = p; // 重置容量 } tmp[req[i]]--; // 消耗一份 if (!tmp[req[i]]) { // 这瓶饮料用完 e[curl[req[i]]].push_back(i); // 记录区间 [l, r] ed[i].push_back(curl[req[i]]); curl[req[i]] = 0; } } // 处理未用完的饮料 for (int i = 1; i <= k; i++) if (curl[i]) e[curl[i]].push_back(n + 1), ed[n + 1].push_back(curl[i]); // 计算到储藏室的代价 for (int i = 0; i <= n + 1; i++) val[i] = min((C & 1) ? (2 * (n + 1 - i) - 1) : 2 * N, (C & 2) ? (2 * i + 1) : 2 * N); }预处理逻辑:
- 区间划分:将每种饮料的需求划分为若干长度为 的区间
- 储藏室代价:
- 如果 (终点有储藏室),代价为
- 如果 (起点有储藏室),代价为
- 如果 (两端都有),取最小值
动态规划求解
void DP() { memset(f, 0x3f, sizeof f), f[0] = 0; int l = 0; priority_queue<int, vector<int>, greater<int>> pq, del; pq.push(f[0] - 0 + 1), pv[0] = f[0] - 0 + 1; int middle = 0, rest = m; for (int i = 1; i <= n + 1; i++) { middle += e[i].size(); // 新增以i开始的区间 // 滑动窗口:确保当前使用的瓶子数不超过m while (middle > rest) del.push(pv[l]), l++, rest += ed[l].size(), rest -= e[l].size(), middle -= e[l].size(); // 清理无效元素 while (!del.empty() and del.top() == pq.top()) del.pop(), pq.pop(); // 状态转移 if (!pq.empty()) f[i] = pq.top() + i - 1; pq.push(f[i] + val[i] - i); pv[i] = f[i] + val[i] - i; } cout << f[n + 1]; }DP核心思想:
f[i]:服务完前 个座位的最小距离- 状态转移:
- 使用优先队列维护 的最小值
- 滑动窗口确保任何时候使用的瓶子数不超过
复杂度分析
- 时间复杂度:,每个位置入队出队一次
- 空间复杂度:,存储区间信息和优先队列
算法正确性
该算法通过将问题转化为区间覆盖和动态规划,利用优先队列优化转移,确保了在满足容量限制的前提下找到最短路径。预处理阶段正确划分了饮料服务区间,DP阶段通过滑动窗口维护了容量约束。
总结
本题的关键在于将饮料服务建模为区间覆盖问题,然后使用带容量约束的动态规划求解。算法通过巧妙的预处理和数据结构优化,在 时间内解决了问题。
- 1
信息
- ID
- 4762
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者