题解
2026-07-28 09:42:28
发布于:山西
9阅读
0回复
0点赞
理解题意:
- 模型抽象
赛道 = 若干矩形的并集,区域连通;智能车只能在并集内部行驶,求 S 到 T 最短路径。几何性质:区域内最短路径拐点只能出现在相邻矩形公共竖边的上下端点。 - 建图节点集合
节点包含:
起点 S、终点 T;
每一段相邻矩形公共竖直边的两个端点。上图公共竖边端点:(2,1)、(2,2)。本例节点列表:S(1,1), T(3,0), P1(2,1), P2(2,2)。
- 连边规则
对任意两个节点 A,B:判断线段 AB 全部落在矩形并集内部,满足则连无向边,边权为两点欧氏距离。本例有效连线:S↔P1,P1↔T,S 不能直接连 T(线段穿过赛道外部)。 - 求最短路
所有节点构建无向图,使用Dijkstra 算法求出起点到终点的最短路径长度 L。答案时间=vL - 关键子问题:线段检验
给定线段 PQ,判断整条线段是否完全被矩形的并覆盖:线段上任意一点 (x,y),至少存在一个矩形,满足:xi1≤x≤xi2,yi1≤y≤yi2实现上可以采样检验,或者参数化离散判断。
样例完整演算
节点:S(1,1),P1(2,1),P2(2,2),T(3,0)有效边:
S−P1,长度 1
P1−P2,长度 1
P1−T,长度 2≈1.41421356
最短路径:S→P1→T总长 1+2≈2.41421356,v=1,输出 2.41421356。
实现要点
收集所有候选拐点(公共竖边端点);
枚举所有节点两两配对,线段合法性检测;
Dijkstra 求最短路径;
路径长度除以速度得到时间,输出至少 6 位小数。
易错提醒
不能直接两点直线!直线可能穿出赛道区域;
拐点只需要公共竖边端点,不需要枚举矩形所有顶点,大幅减少节点数量;
浮点数运算注意精度,输出保证不少于 6 位小数。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n;cin>>n;
vector<array<int,4>> rects(n);
for(auto&v:rects)for(int&x:v)cin>>x;
int xs,ys,xt,yt,ex=0;
double v;cin>>xs>>ys>>xt>>yt>>v;
if(xs==xt){
printf("%.8lf\n",(double)abs(ys-yt)/v);
return 0;
}
if(xs>xt)swap(xs,xt),swap(ys,yt);
vector<int>x,y,tp;
x.reserve(2*n+5);y.reserve(2*n+5);tp.reserve(2*n+5);
auto add=[&](int _x,int _y,int _tp){x.emplace_back(_x);y.emplace_back(_y);tp.emplace_back(_tp);};
add(xs,ys,0);
for(int i=1;i<n;++i){
auto&r=rects[i];
if(r[0]<=xs){
if(r[0]==xs){
if(ys>r[3])ex+=ys-r[3],y[0]=r[3];
else if(ys<r[1])ex+=r[1]-ys,y[0]=r[1];
}
continue;
}
if(r[0]>=xt){
if(r[0]==xt){
auto&pr=rects[i-1];
if(yt>pr[3])ex+=yt-pr[3],yt=pr[3];
else if(yt<pr[1])ex+=pr[1]-yt,yt=pr[1];
}
break;
}
auto&pr=rects[i-1];
add(r[0],min(pr[3],r[3]),1);
add(r[0],max(pr[1],r[1]),2);
}
add(xt,yt,1);
int m=x.size();
vector<double>f(m,1e18);
f[0]=0;
for(int i=1;i<m;++i){
double lo=-1e18,hi=1e18;
int s=i-tp[i];
for(int j=s;j>=0;--j){
int dx=x[i]-x[j],dy=y[i]-y[j];
double k=(double)dy/dx;
if(lo<=k&&k<=hi)f[i]=min(f[i],f[j]+hypot(dx,dy));
if(tp[j]==1)lo=max(lo,k);
else if(tp[j]==2)hi=min(hi,k);
if(lo>hi)break;
}
}
printf("%.8lf\n",(f.back()+ex)/v);
}
这里空空如也








有帮助,赞一个