news 2026/10/17 1:16:18

evo轨迹评估工具:SLAM与视觉里程计精度分析实操指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
evo轨迹评估工具:SLAM与视觉里程计精度分析实操指南

我第一次跑通视觉里程计demo的时候,把估计轨迹和真值轨迹画在同一张图上,两条线贴得很近,我当时觉得这次算法调参稳了。结果同组的A同学顺手用evo跑了一段,看到输出数值之后,我们俩都沉默了——原来视觉上的“贴合”只是假象。这个问题几乎每个接触SLAM或者视觉里程计的人都会遇到:你缺的不是调参,而是一套标准化的轨迹评估方法。evo就是解决这个问题的命令行工具,它能读取多种常见轨迹格式,完成位姿对齐、时间戳匹配,然后计算绝对轨迹误差(APE)和相对位姿误差(RPE),并输出统计指标、图表和可复现的结果文件。如果你刚跑通某个里程计算法,或者正在写实验报告、准备横向对比不同方案,这篇文章应该能帮你少走很多弯路。

1. 评估轨迹这件事,为什么这么麻烦

1.1 三个绕不开的问题

任何轨迹评估,结果无非是估计轨迹和参考轨迹之间的偏差。第一个问题在于两条轨迹往往不在同一个坐标系里。算法输出的是以起始位置为原点的局部坐标系轨迹,参考轨迹则是全局坐标系下的真值,直接把对应点坐标相减,误差大得离谱,而且没有意义。我见过不少第一次做评估的同学,拿着还没对齐的两条轨迹就去算RMSE,算出来的数字自己都不敢信。

第二个问题在于时间戳对不上。传感器帧率和真值记录频率不一样,某个时刻的估计位姿和参考位姿差了几毫秒,你需要先做时间同步,否则误差里混入的是时间偏差而不是位姿误差。第三个问题是尺度。单目视觉里程计只有图像没有深度,估计轨迹在尺度上可能整体放大或缩小,这种尺度漂移如果不处理,绝对误差就完全没有参考价值。这三个问题叠加在一起,导致早期团队经常各写各的评估脚本,有的用MATLAB,有的用Python,不同脚本算出来的结果相互之间完全不可比。

1.2 evo覆盖了评估全链路

evo把这个过程标准化了,它做的事情可以概括为四块:读取轨迹、对齐轨迹、计算误差、输出结果。读取方面支持多种常见格式,比如带时间戳的文本位姿格式、矩阵形式的轨迹记录、机器人中间件记录的数据格式都能解析。对齐方面提供刚体变换对齐和带尺度修正的对齐,分别适用于尺度已知和尺度未知的系统。误差计算实现了两大类指标:绝对轨迹误差和相对位姿误差。输出上,除了在终端打印统计量,还可以保存图表和zip结果文件,方便后续横向对比。

我觉得它最大的贡献不是这些功能本身,而是把评估的“度量衡”统一了。同一个数据集,不管你是用视觉SLAM、视觉惯性里程计还是激光里程计,只要导出的轨迹文件格式符合规范,就能用同一条命令、同一套指标来比较。很多人觉得evo是个“画图工具”,实际用了才知道,它更像是一整套评估规范,命令只是壳。

1.3 什么时候不需要用evo

如果你只是想把轨迹画出来看个大概形状,用Python matplotlib或者其他可视化工具更快,没必要上evo。如果项目里已经有了一套固化的内部评估流程,所有实验都用同一套老脚本,结果也一直有人认,那也不一定非要换。但如果你要做算法对比、写论文或技术报告、或者想快速定位一个里程计demo的问题,evo是最省事的选择。它不挑剔你是用什么框架跑出来的结果,PyTorch也好、传统几何方法也好,只要导出成它支持的格式,就能进入统一的评估流程。

2. 安装evo以及环境里最常见的坑

2.1 推荐用独立虚拟环境

evo是纯Python工具,安装本身不难,难的是依赖环境。很多开发者在一台装了一堆深度学习框架的工作站里直接执行pip install evo,结果numpy版本冲突,或者matplotlib导入报错。我自己习惯先建一个虚拟环境,专门放评估工具,避免和日常开发环境互相污染。下面是完整的安装命令:

python3 -m venv evo_env source evo_env/bin/activate pip install evo --upgrade --no-binary evo

这里--no-binary evo这个参数比较关键,它让pip走源码安装而不是直接拉预编译的wheel包,实测能避开很多二进制兼容问题。如果你的网络环境下载源码包比较慢,也可以先去官方文档确认一下当前版本对Python版本的要求,再决定要不要去掉这个参数。另外我建议Python版本选3.8到3.10之间的较新版本,太老的版本容易遇到语法兼容问题。

2.2 经常出现的依赖报错

我整理了几个出现频率极高的环境问题,基本覆盖了大多数安装失败场景:

问题现象典型报错原因解决办法
numpy版本不匹配numpy.core.multiarray failed to import环境中numpy版本与evo不兼容在虚拟环境里重新安装合适的numpy版本
matplotlib画图窗口打不开报错找不到TkAgg服务器没有图形界面设置后端为Agg,只保存图片不弹窗
源码安装下载超时网络连接中断网络原因换用官方预编译包或配置合适的下载源

遇到第一类问题,不要急着卸载重装整个环境。我的排查习惯是先把numpy版本和evo要求的版本范围对照一下,大多数情况只要把numpy固定到大版本2.x之前就能解决。第二类问题在远程服务器里非常常见,尤其容器环境,装上evo之后一执行--plot就报错弹不了窗。其实这不是evo的问题,而是matplotlib找不到图形后端,设置一下环境变量就行。第三类问题主要看网络,没有太多技术含量,多试几次或者调整安装方式即可。

2.3 安装之后必须做的验证

安装完成后别急着跑自己的数据,先用帮助命令确认环境可用:

evo_traj --help evo_ape --help evo_rpe --help

如果这三个命令能正常输出帮助信息,说明安装基本成功。接下来再找一个最小轨迹文件测试画图和误差计算,确认matplotlib后端和结果保存功能没问题。我自己遇到过一种情况:帮助命令正常,但一执行--plot就报错,后来发现是环境里缺少某个图形库,好在设置MPLBACKEND=Agg之后问题消失。逐条验证是排查环境问题的通用套路,别嫌麻烦,这一步做扎实了,后面所有命令跑起来才顺。

3. 三个核心命令:evo_traj、evo_ape、evo_rpe

3.1 evo_traj:轨迹文件的分析与可视化

evo_traj是第一个要熟悉的命令,做的事情包括读取轨迹文件、查看基本信息、比较多条轨迹、格式转换、画图。它最典型的使用场景是把估计轨迹和参考轨迹放在同一张图里看整体形态:

evo_traj tum est.txt --ref=ref.txt -p

这里的tum表示输入文件是带时间戳的文本位姿格式,每一行由时间戳、位置xyz、四元数xyzw组成。--ref指定参考轨迹,-p表示绘制轨迹图。如果你有两个算法的估计轨迹想同时显示,可以这样写:

evo_traj tum est1.txt est2.txt --ref=ref.txt -a -p

-a会让两条估计轨迹都对齐到参考轨迹再显示,这样不同算法可以在同一坐标系下比较,视觉上更直观。除了画图,evo_traj还可以做格式转换,比如把文本轨迹转成矩阵形式,方便交给其他工具处理。类似--save_as_kitti这样的输出参数,具体支持的格式以及参数名在不同版本里略有差异,执行命令前扫一眼evo_traj --help最稳妥。

这里有一个容易被忽视的小细节:多条轨迹画在一起时,如果轨迹长度差异很大,比如一条跑了两分钟、一条只跑了三十秒,画出来的结果很难看,而且可能会误判精度。所以我一般会先确认所有轨迹的时间范围基本一致,再做可视化。

3.2 evo_ape:绝对轨迹误差

evo_ape计算的是估计轨迹整体和真值轨迹之间的差距。实际计算时,先把两条轨迹做对齐处理,再按时间对应起来,在每个时间点取位姿差,统计出RMSE等指标。它适合回答一个问题:整体漂移到底有多大。一个常用命令是:

evo_ape tum ref.txt est.txt -a -va --plot --save_results results/ape.zip

参数含义拆开来看:-a表示自动对齐估计轨迹到参考轨迹,-va表示打印详细统计量,包括rmse、mean、median、std、min、max,--plot绘制误差图,--save_results把结果打包成zip供后续汇总。命令跑完之后,输出里最重要是rmse和max两个值。rmse反映整体误差水平,max反映最差时刻的表现。很多SLAM系统的验收指标直接卡在max上,因为在移动机器人场景里,最大的那次定位错误往往就是事故根源。

3.3 evo_rpe:相对位姿误差

APE回答的是整体漂移多少,但两个算法可能绝对误差接近,一个一路平稳,另一个剧烈抖动,这两个对应用的影响完全不同。RPE把轨迹按固定间隔切成小段,统计每一段内位姿变化的误差,更适合评价局部的平滑性和一致性。常用命令:

evo_rpe tum ref.txt est.txt -a -r trans_part -d 1 -va --plot --save_results results/rpe.zip

-r trans_part表示只取位姿变化中的平移部分,-d 1表示间隔为一帧。如果换成-r rot_part,就会关注旋转部分。不同场景关注点不同,轮式机器人平移误差更重要,陀螺仪或旋转类标定更关注旋转误差。需要提醒的是,RPE里的这个间隔步长不是随意设置的,它本质上是考察多少距离内的局部一致性,一般从1帧或0.1米起步,根据你的实际应用需求调整。

3.4 evo_res:批量结果的横向对比

单独一次评估没有说服力,横向对比才是常态。把每次evo_ape或evo_rpe保存的zip结果收集起来,交给evo_res:

evo_res results/ape_alg1.zip results/ape_alg2.zip -p

它会生成一个汇总表格,把每个结果的关键统计量排在一起,还可以绘制柱状图或箱线图。我自己的习惯是把每次实验结果统一用--save_results保存到一个目录,文件名带上算法代号和数据集代号,最后批量执行evo_res,几组实验的差距一目了然。这个汇总能力在有大量实验需要对比时非常关键,尤其几个算法看起来差不多时,表格能把差异用数字客观呈现出来,比肉眼判断靠谱得多。

4. 轨迹对齐:评估结果是否可信的分水岭

4.1 为什么直接比位姿没有意义

两条轨迹放在一起之前,必须回答坐标系和参考点的问题。估计轨迹往往从某一时刻的相机位姿开始,参考轨迹是另一套坐标,两者原点不同、旋转方向不同,直接计算对应位姿差,结果只是坐标系差异,不是算法误差。把估计轨迹对齐到参考轨迹,本质上是在估计一个刚体变换(旋转加平移),再用这个变换把估计轨迹转到参考坐标系下,最后做误差统计。

evo做得比较多的是基于最小二乘的刚体对齐,也有带尺度修正的版本,适用于单目这类存在尺度模糊的方案。这段逻辑听起来简单,但从我实际踩过的坑来看,很多人把“比较”理解得太简单,以为只要文件格式对、时间戳对上就能算误差,完全忽略了对齐步骤。这样算出来的数字不仅没有意义,还会让你对算法的判断产生严重偏差。

4.2 参数对应不同需求

不同参数对应不同场景,我整理了一个常用对照表:

参数对齐方式适用场景
-a刚体SE(3)对齐双目、深度相机、视觉惯性系统等尺度已知方案
-as刚体对齐加尺度修正单目里程计、单目SLAM等存在尺度模糊的方案
-s只修正尺度已知旋转平移、只想评估尺度偏差的场景

这里有一个容易被忽略的点:对齐本身会吸收掉一部分系统误差,所以它反映的是算法在自身坐标系下的相对一致性,而不是全局坐标系下的绝对精度。如果你的应用需要全局坐标,比如建图任务,那不进行对齐的评估更贴近真实运行情况。但如果是算法横向对比,建议所有算法都用同一套对齐方式,否则结果没有公平性。

4.3 什么时候不该用对齐

假设你的系统是一个固定标定过的视觉惯性系统,输出轨迹和真值已经处在同一坐标系下,这时用-a反而会把真实的系统级误差掩盖掉。我的建议是先想清楚系统本身有没有经过外参标定,坐标系是否统一,再决定是否启用对齐。如果没有统一标定或涉及多传感器融合,一般默认用-a或-as做对比。

另外,对齐参数的设定一定要写进实验记录里。我自己吃过这个亏:隔了一个月回看几组旧结果,完全想不起当时用的是-a还是-as,导致对同一批数据做出了完全不同的评价。后来我把命令原文、参数、数据集代号都存到一个实验清单文件里,回看结果时直接对照清单,再也没出过这种问题。

5. 一次完整评估的实战流程

5.1 准备轨迹文件

手工构造一个最小示例。文本格式每一行是:时间戳(秒)、位置xyz、四元数xyzw。比如:

0.000 0.000 0.000 0.000 0.000 0.000 0.000 1.000 0.100 0.010 0.000 0.000 0.000 0.000 0.000 1.000 0.200 0.020 0.000 0.000 0.000 0.000 0.000 1.000

这个格式在evo里对应的类型标识是tum。实际项目中,很多公开数据集会直接提供这个格式的真值文件,你只需要把算法输出的轨迹导出成同样的格式。导出时最需要注意的是时间戳单位,秒和纳秒混用是后续一堆问题的根源,建议统一转成秒再存文件。

5.2 可视化并做初步检查

先把估计轨迹和参考轨迹画出来做个初步检查:

evo_traj tum est.txt --ref=ref.txt -p

这时候先做三个检查:轨迹是否有明显跳点;起点是否大致一致;时间戳范围大概覆盖多长时间。如果这一步发现异常,不要继续评估,先回头检查算法输出。轨迹里出现飞点或者时间戳乱序,再认真评估也没有意义,因为你的数据本身就是脏的。

5.3 计算APE并保存zip

evo_ape tum ref.txt est.txt -a -va --plot --save_results results/ape_est.zip

保存结果后,注意终端打印的rmse和max。如果rmse数值很高,但图上轨迹看起来不错,最可能的原因是轨迹没有被正确对齐,或者时间戳匹配效果差。这个矛盾现象是评估中最常见的坑,也是新手最容易困惑的地方。你可以试着不加-a再跑一次,对比两次结果的差异,就能判断误差主要来自坐标系偏置还是算法本身。

5.4 计算RPE并保存zip

evo_rpe tum ref.txt est.txt -a -r trans_part -d 1 -va --plot --save_results results/rpe_est.zip

如果RPE结果显著小于APE,说明主要误差来自累积漂移,而不是单帧噪声。如果两者都很高,说明算法本身估计质量较差,可能需要检查前端特征匹配或后端优化。我通常会把APE和RPE两组指标一起看,因为它们互补:APE告诉你总误差有多大,RPE告诉你误差是怎么累积的。

5.5 汇总多个算法的结果

再准备一组不同参数或不同算法跑出的轨迹,重复上面的步骤,保存不同的zip文件,最后:

evo_res results/*.zip -p

results/*.zip依赖shell通配符,会把目录里所有zip结果文件全部读进来。终端会显示一张包含所有算法统计量的汇总表,这张表可以直接放进实验记录里,比手动复制粘贴数值可靠得多。汇总表的可复现性,是命令行工具相比图形界面最大的优势——你保存的是结果包,而不是一张截图。

6. 统计指标怎么读,才不会被数字误导

6.1 APE和RPE的指标含义

evo输出的统计量一般包括rmse、mean、median、std、min、max。RMSE对误差中的大值更敏感,适合体现最差部分的惩罚;mean比较直观但容易被极值带偏;median对异常值更稳健。如果rmse和mean差距很大,说明存在少量误差很大的帧,需要重点排查。

当多组实验对比时,我建议至少记录rmse和max两个值。因为很多场景里,平均误差低但偶发大误差会对系统可用性造成严重影响。拿移动机器人举例,整体平均误差也许只有0.1米,但偶尔一次0.5米的定位跳变,就足以让机器人在狭窄通道里撞上障碍物。只看mean会掩盖这类风险。

6.2 一个典型的“看起来好但数值差”问题

我举一个常见假象:估计轨迹和真值轨迹整体形状一致,但整体绕参考轨迹某个点旋转了一个角度。肉眼在俯视图上几乎看不出来,尤其当轨迹很长且来回重叠时,APE的rmse却可能很大。这时你用-a重新对齐,会看到数值明显下降,这就说明主要误差来自坐标系初始对齐问题,而不是算法漂移。

反过来,如果对齐后rmse仍然很高,说明算法本身存在系统性偏差。最典型的表现是回环前和回环后的轨迹不重合,在评估图上会看到明显的“闭合差”。这种问题依靠单纯提高单帧精度往往治不好,通常需要检查回环检测和位姿图优化,而不是继续调前端特征。

6.3 看图时的关键检查点

画出来的图一般包含轨迹俯视图、误差与时间曲线、误差分布直方图。我通常按三步看:第一,看误差曲线里有没有明显尖峰,尖峰对应的时间点就是算法最容易出错的时刻;第二,看误差分布是近似高斯还是长尾,长尾分布说明少数大误差主导整体指标;第三,看多条轨迹曲线在回环处是否闭合。这些信息比一个简单的rmse数字更有诊断价值。

有时候你会发现误差曲线呈现周期性波动,这很可能是传感器数据本身的问题,比如运动平台周期性经过某个特征稀疏区域。这时候结合时间戳查找对应的场景片段,定位问题会比对着数字发呆有效得多。

7. 高频坑位与排查思路

7.1 时间戳单位不一致

运行evo_ape后提示找不到足够多的匹配位姿,或者匹配到的数量极少,这种情况先查时间戳单位。估计轨迹和参考轨迹的时间戳一个用秒,一个用纳秒,差了一千甚至一百万倍,能匹配上才奇怪。

排查链路很清晰:先查看两个文件的头部,对比时间戳数字量级;然后用evo_traj tum est.txt ref.txt -p画图,如果两条轨迹在时间轴上没有重叠区域,说明时间差异很大。解决方式是把纳秒除以1e9转成秒,或者反过来全部转成纳秒。另外还要注意,有些数据集带的时间戳本身就不完全对齐,需要设置合理的最大时间差。

7.2 轨迹点数相差悬殊导致的对齐配对失败

参考轨迹有几千帧,估计轨迹只有几十帧,即使加了-a,误差依然异常,这时候要检查轨迹关联。默认的轨迹关联需要按时间戳配对,如果两条轨迹没有同时刻附近的位姿,配对数量太少,统计结果没有代表性。

排查链路是:分别确认两个文件的行数,比如用wc -l;再用evo_traj带上--ref画图,观察两条轨迹的时间范围。解决方式是在算法端确保估计轨迹和真值时间范围重叠足够,再评估。如果只是从测试集里截取了一段数据,你需要对应截取参考轨迹,而不是拿整段真值去对比一小段估计轨迹。

7.3 单目轨迹不修尺度直接评估

单目里程计存在尺度漂移,这是系统本身的原理性限制,不处理尺度就评估绝对误差,结果必然差得离谱。很多人第一次拿到单目轨迹,直接拿evo_ape tum ref.txt est.txt -a -va跑,发现加了-a结果还行,去掉对齐后rmse巨大,就开始怀疑算法是不是写错了。

排查链路也不复杂:先计算估计轨迹总里程和真值总里程的比值,如果不是接近1,基本就是尺度问题。解决方式是对比单目算法时统一使用-as对齐,并在记录里注明“带尺度修正”。这里还要强调一点:尺度修正并不总是正当的,如果你的实际应用要求尺度准确,比如需要恢复真实尺寸的建图任务,那么单目方案本身就先要解决尺度恢复问题,评估时也不应该用-as掩盖这个缺陷。

7.4 远程服务器上画图卡死或报错

在服务器上加了--plot,窗口弹不出来或程序直接退出,原因是服务器没有图形界面,matplotlib找不到可用后端。这种现象在容器环境和远程开发环境里特别常见。

解决方式是把后端设为Agg,指定后端之后再执行画图就不会试图弹窗,但图片文件依然会正常保存。命令是这样:

export MPLBACKEND=Agg

如果你在Python脚本里调用evo的绘图功能,也可以在代码开头加一行matplotlib.use("Agg")。养成固定设置后端的习惯能省很多事,不然换一台机器就可能因为图形环境差异而出奇怪问题。

8. 用Python API做定制化评估

8.1 命令行不够的时候

命令行方便,但做批量实验时重复执行、解析终端输出并不高效。比如你想遍历多个数据集、多组参数,把每个结果收集进一张总表,命令行就力不从心了。evo提供了Python API,你可以把读取、时间同步、误差计算、绘图全部写进脚本里,批量运行。

我自己的转折点发生在一次参数扫描实验里:命令行逐条执行太慢,而且结果都在zip里,还得手动整理。后来改成API批量处理,几十组实验一次跑完,输出直接汇总成CSV,效率提升了不止一个量级。

8.2 一个最小可用的评估脚本

参考流程如下,注意evo版本差异比较大,不同版本的API签名可能不同,以你安装版本的帮助为准:

import matplotlib matplotlib.use("Agg") from evo.tools import file_interface from evo.core import sync from evo.core.metrics import APE, PoseRelation, Unit ref_traj = file_interface.read_tum_trajectory_file("ref.txt") est_traj = file_interface.read_tum_trajectory_file("est.txt") ref_traj, est_traj = sync.associate_trajectories(ref_traj, est_traj, max_diff=0.01) ape = APE(PoseRelation.translation_part, Unit.meters) ape.process_data((ref_traj, est_traj)) stats = ape.get_statistic() print("APE rmse:", stats["rmse"])

这段代码表达的是完整流程:读取、关联、构造APE指标、处理数据、取统计量。实际使用中,你也可以把多组结果存入一个列表,循环计算并追加到数据表。需要注意,不同版本里read_tum_trajectory_file这类函数可能存在或改名,最好先执行dir(file_interface)看一下有哪些可用函数。

8.3 结合现有训练流程

如果你的里程计系统是在深度学习框架里训练的,评估脚本还可以在训练结束后自动触发,把每个epoch的轨迹误差写入日志。这个自动化能力是命令行工具最难给到的。我在模拟项目X里就是这么用的:训练完自动评估、自动生成趋势图,几个版本模型的精度变化一眼就能看明白。

最后再给一个批量使用的建议:不管你是用命令行还是API,所有实验的轨迹文件命名、时间戳单位、是否对齐,这些元信息一定要记录清楚。很多问题在几周后回看时,其实都是因为记不清当时的评估条件。把评估命令连同数据集代号一起写进实验记录,能省掉大量返工时间。

如果你只是日常验证一个算法的精度,命令行就足够了;如果你要连续跑几十组实验,那就值得把API脚本固化下来。我在模拟项目X里把它做成了训练流程的最后一步,每次训练结束自动评估、自动画误差曲线,效率确实比手动跑命令高很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 1:15:57

S5PV210交叉编译器安装全指南:从工具链选型到Hello World

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 1:15:53

彻底搞懂SIFT:从尺度空间到OpenCV特征匹配与调参实战

简介:基于尺度不变特征变换(SIFT)的Python实现与OpenCV调用资源包,面向需要实现SIFT算法或借助OpenCV快速提取特征的计算机视觉学习者、研究者和开发者,可应用于图像匹配、物体识别、三维重建、全景拼接等场景。压缩包…

作者头像 李华
网站建设 2026/10/17 1:15:47

C语言处理CSV文件:状态机解析器设计与完整实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 1:15:43

Python猜拳小游戏实战:从零到一掌握编程核心逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 1:15:20

单纯形法与大M法实战:从SciPy调库到手写Python实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 1:15:19

P1070道路游戏:对角线前缀和+单调队列优化DP详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华