扫描线优化最短路例题(待学习)
https://www.codechef.com/submit/ROCKET_PACK?tab=statement
主要思路为,转化为最短路问题,然后对全部点进行扫描。
active集合按dis排序,remove集合按到达边界排序。
当到某点i时,先根据remove,对到达边界小于i(已经不会被用于后续更新)的更新,在active和remove中删除;
然后在active集合中获取最短dis的更新,然后在集合中放入距离为dis+c(到下一个节点的dis)以及到达边界为h+e(高度+能量即为可到达点的边界)的更新。
代码:

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<long long, long long> PLL; typedef pair<LL, PLL> PLLL; #define fi first #define se second void YD() { int m,n, k; cin >> m >>n>> k; vector<PLLL> points; LL x,y, c, e; while (k--) { cin >> x >> y >> c >> e; points.push_back({ x + y,{c,e} }); } points.push_back({ n + m, { 0,0 } }); sort(points.begin(), points.end()); set<PLL> active;//dis,to_height set<PLL> remove;//to_height,dis LL ans = 0; remove.insert({ 0,0 }); active.insert({ 0,0 }); for (auto& [h, ce] : points) { auto [c, e] = ce; while (!remove.empty()) { auto [height, dis] = *remove.begin(); if (height < h) { remove.erase({ height,dis }); active.erase({ dis,height }); } else break; } if (active.empty()) { cout << -1 << endl; return; } auto [dis,height] = *active.begin(); if (h == n + m) { cout << dis << endl; return; } LL nxt = dis + c; active.insert({ nxt,h + e }); remove.insert({ h + e,nxt }); } cout << -1 << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int T = 1; cin >> T; while (T--) { YD(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人