斜率优化DP:从几何直观到代码实现,详解动态规划优化技术
1. 从暴力到优雅斜率优化DP的思维跃迁搞算法竞赛或者研究动态规划优化的朋友对“斜率优化”这四个字应该不陌生。它经常出现在一些看似简单的序列分割、任务安排问题里但数据范围一大朴素的O(n²) DP就会立刻超时。我第一次遇到这类问题是在处理一个经典的生产线调度模型上题目大意是有一批任务需要按顺序处理每个任务有准备成本和执行成本任务可以分批每批有一个固定的启动开销目标是让总成本最小。写了个二维DP一交上去就TLE看着n10^5的数据范围直挠头。后来啃了半天论文和题解才把“斜率优化”这个工具真正装进自己的工具箱。今天这篇笔记就结合我踩过的坑和刷过的题把斜率优化DP的核心思想、推导细节、代码模板以及那些容易写错的边界情况掰开揉碎了讲清楚。无论你是正在备赛的选手还是对算法优化感兴趣的开发者相信这篇都能帮你打通任督二脉。简单说斜率优化是用来解决一类特定状态转移方程优化问题的技术。这类方程通常长这样dp[i] min{ dp[j] f(j) * g(i) h(i) c(j) }其中min或max括号里的东西能通过变形变成一个关于f(j)和dp[j] c(j)的线性表达式。它的核心思想是把每个决策点j想象成平面上的点(x, y)把状态i的转移看作是用一条固定斜率的直线去切这些点找最优截距。听起来有点抽象别急我们一步步来。2. 问题模型与暴力DP的瓶颈我们从一个最经典的模型开始讲起这样更有抓手。假设有n个任务每个任务有一个权值a[i]任务必须按顺序完成。现在要把这些任务分成若干连续组批每完成一组会产生一个代价这个代价由该组任务的权值总和以及一个与分组方式有关的函数决定。很多实际问题都能抽象成这个模型比如任务分批问题每组有固定的启动时间或成本S第j1到第i个任务作为一组时代价为S sum(a[j1:i]) * T(i)其中T(i)可能与i有关。打印文章/书籍排版每行有固定宽度一行内单词间的空格会产生一个丑陋度目标是使总丑陋度最小。这其实就是著名的“序列分割”问题。仓库建设/物流运输在一条直线上有n个地点需要选择若干地点建仓库货物从产地运到仓库有费用建仓库也有费用目标是总费用最小。这类问题最直观的DP设计是设dp[i]表示处理完前i个任务的最小总代价。sum[i]为前缀和即sum[i] a[1] a[2] ... a[i]。 那么转移方程通常可以写成dp[i] min{ dp[j] w(j1, i) }其中0 j iw(j1, i)表示将区间[j1, i]的任务分为一组所产生的代价。暴力DP的瓶颈就在于这个min操作需要枚举所有可能的j复杂度是O(n²)。当n达到10^5甚至更大时这显然是不可接受的。斜率优化要做的就是利用代价函数w的特殊形式将转移优化到O(n)或O(n log n)。为了让推导更具体我们使用一个最经典、最标准的斜率优化模型作为例子假设代价函数为w(j1, i) (sum[i] - sum[j])^2 C其中C是一个常数。 那么状态转移方程为dp[i] min{ dp[j] (sum[i] - sum[j])^2 C } 其中0 j i 我们约定sum[0] 0, dp[0] 0。3. 代数变形从min到直线方程斜率优化的第一步也是关键的一步是进行代数变形将转移方程中与i和j相关的项分离。我们对目标转移式进行展开和变形假设对于当前要计算的dp[i]最优决策点是j。那么有dp[i] dp[j] (sum[i] - sum[j])^2 C展开平方项dp[i] dp[j] sum[i]^2 - 2*sum[i]*sum[j] sum[j]^2 C移项将与j无关的项移到左边dp[i] - sum[i]^2 - C dp[j] sum[j]^2 - 2*sum[i]*sum[j]观察这个等式。右边同时包含了i和j。我们进行一个关键的换元令y(j) dp[j] sum[j]^2x(j) sum[j]k(i) 2 * sum[i]b(i) dp[i] - sum[i]^2 - C于是上面的等式变成了一个标准的直线方程形式b(i) y(j) - k(i) * x(j)这个变形的意义何在现在对于每个已经计算出来的状态j我们可以在二维平面上确定一个点P_j (x(j), y(j))即(sum[j], dp[j] sum[j]^2)。 对于当前要计算的状态i我们有一条斜率固定为k(i) 2 * sum[i]的直线。b(i)就是这条直线在y轴上的截距。 我们的目标dp[i] min{...} 根据变形后的等式b(i) y(j) - k(i)*x(j) 等价于对于给定的斜率k(i)找一点P_j使得过P_j且斜率为k(i)的直线的截距b(i)最小因为dp[i] b(i) sum[i]^2 C后两项是常数最小化dp[i]等价于最小化b(i)。注意这里有一个非常重要的前提我们要求k(i)是单调的x(j)也是单调递增的。在这个例子中因为sum[i]是前缀和如果a[i]非负那么sum[i]和k(i)都是单调递增的。这个单调性是后续能用单调队列将复杂度降到O(n)的关键。如果k(i)不单调则需要用更复杂的数据结构如平衡树、CDQ分治来维护凸壳复杂度为O(n log n)。4. 几何直观与凸壳维护理解了代数变形的几何意义我们就进入了斜率优化的核心维护一个“下凸壳”。什么是凸壳想象平面上有一系列点P_j。一个点集的下凸壳就是连接最左点和最右点并且所有点都在连线之上或之上的折线。更技术地说是这些点按x坐标排序后相邻点连线斜率单调递增的那条“下包络线”。为什么是最小化截距对于一条斜率为k的直线我们要让它尽可能往下移减小截距b直到碰到某个点。这个“碰到的点”就是所有点中使得y - k*x最小的那个点。从几何上看如果把这条直线从负无穷远处向上平移它第一次触碰到的点就是最优决策点。如何快速找到这个点如果所有决策点P_j构成了一个下凸壳那么对于单调递增的斜率k(i)最优决策点也在凸壳上单调移动。这就像用一根斜率不断变大的棍子从凸壳的左下端开始向右上方“扫”过去棍子与凸壳的切点就是最优决策点。维护凸壳的具体操作单调队列实现我们用一个双端队列q[]来维护构成下凸壳的点存储的是点的编号j我们可以通过j得到x(j), y(j)。检查队首有效性维护决策单调性 对于当前状态i其斜率k(i)是固定的。队列中保存了多个候选点。如果队列前两个点q[head]和q[head1]构成的直线的斜率slope(q[head], q[head1]) k(i)那么对于斜率更大的k(i)来说点q[head]永远不可能成为最优决策因为直线会先碰到q[head1]所以可以将队首q[head]弹出。重复此过程直到队列头两个点构成的斜率大于k(i)。此时队首q[head]就是当前状态i的最优决策点j。计算dp[i] 利用队首j q[head]直接代入转移方程计算dp[i]。同时计算出新点P_i的坐标(x(i), y(i))。将新点P_i加入凸壳维护凸壳性质 将点i加入队列尾部。但加入前需要检查加入后是否会破坏凸壳的“下凸”性质。设队列尾部三个点依次为q[tail-1],q[tail],i。我们需要保证从q[tail-1]到q[tail]的斜率小于从q[tail]到i的斜率。如果slope(q[tail-1], q[tail]) slope(q[tail], i)那么点q[tail]就在q[tail-1]和i的连线之上或共线它就不是凸壳上的点了应当从队尾弹出。重复此过程直到满足凸壳性质再将i加入队尾。斜率计算的细节与防误差 斜率通常用浮点数计算但为了避免精度误差在竞赛中普遍采用交叉相乘的方法进行比较。 假设有两个点P1(x1, y1),P2(x2, y2) 斜率s12 (y2 - y1) / (x2 - x1)。 比较s12 k 等价于(y2 - y1) k * (x2 - x1)。 比较s12 s23 等价于(y2 - y1)*(x3 - x2) (y3 - y2)*(x2 - x1)。 这样全程使用整数运算避免了浮点误差。5. 代码模板与逐行解析下面给出针对我们例子dp[i] min{ dp[j] (sum[i] - sum[j])^2 C }的完整C斜率优化DP代码模板并附上详细注释。#include bits/stdc.h using namespace std; typedef long long ll; // 通常需要long long防止溢出 const int MAXN 1e5 10; int n; ll C, a[MAXN], sum[MAXN], dp[MAXN]; int q[MAXN]; // 单调队列存储决策点下标j int head, tail; // 队首队尾指向下一个可插入位置 // 计算点j的纵坐标y inline ll Y(int j) { return dp[j] sum[j] * sum[j]; // y(j) dp[j] sum[j]^2 } // 计算点j的横坐标x inline ll X(int j) { return sum[j]; // x(j) sum[j] } // 计算斜率 (y2-y1)/(x2-x1) 通过交叉相乘比较 inline bool slope_check(int j1, int j2, int j3) { ll x1 X(j1), y1 Y(j1); ll x2 X(j2), y2 Y(j2); ll x3 X(j3), y3 Y(j3); // 判断 slope(j1, j2) slope(j2, j3) ? // 即 (y2-y1)/(x2-x1) (y3-y2)/(x3-x2) ? // 交叉相乘注意这里可能溢出确保使用long long return (y2 - y1) * (x3 - x2) (y3 - y2) * (x2 - x1); } int main() { // 假设输入n, C, 以及数组a[1..n] cin n C; for (int i 1; i n; i) { cin a[i]; sum[i] sum[i - 1] a[i]; // 计算前缀和 } // 初始化队列0号状态一个任务都没处理作为初始决策点 head tail 0; q[tail] 0; // 将点0入队 dp[0] 0; for (int i 1; i n; i) { // 1. 维护队首弹出斜率小于等于当前k(i)的点 // k(i) 2 * sum[i] // 判断 slope(q[head], q[head1]) 2*sum[i] ? // 即 (Y(q[head1]) - Y(q[head])) 2*sum[i] * (X(q[head1]) - X(q[head])) while (head 1 tail Y(q[head 1]) - Y(q[head]) 2 * sum[i] * (X(q[head 1]) - X(q[head]))) { head; } int j q[head]; // 最优决策点 // 2. 计算dp[i] dp[i] dp[j] (sum[i] - sum[j]) * (sum[i] - sum[j]) C; // 3. 将新点i加入队列维护凸壳下凸性质 // 判断队尾两点和i的斜率关系如果尾部点不满足下凸则弹出 while (head 1 tail slope_check(q[tail - 2], q[tail - 1], i)) { tail--; } q[tail] i; // 将i加入队尾 } cout dp[n] endl; return 0; }模板使用要点X(j),Y(j)函数需要根据你具体的变形公式来写。核心是找到变形后b y - k*x中的x和y。slope_check函数是比较斜率用于维护凸壳。注意不等号方向这里维护的是下凸壳斜率单调递增所以当slope(j1, j2) slope(j2, j3)时需要弹出j2。如果维护的是上凸壳求最大值斜率单调递减不等号方向可能相反。队首维护时的比较是与当前状态的斜率k(i)比较。同样需要注意不等号方向目标是找到第一个斜率大于k(i)的线段对应的左端点。初始状态dp[0]通常需要预先定义好并加入队列。6. 经典例题分析与变种掌握了模板我们来看几个变种理解如何将不同问题“转化”到斜率优化的框架下。例题1任务安排洛谷P2365题目描述有N个任务排成序列必须按顺序完成。将任务分成若干批每批包含连续若干个任务。第i个任务单独完成所需时间是T[i]费用系数是C[i]。每批任务开始前需要启动时间S。同一批任务在同一时刻完成每个任务的完成时刻就是其所在批的结束时刻。每个任务的费用是其完成时刻乘以费用系数。求最小总费用。推导过程设dp[i]为处理完前i个任务的最小费用。sumT[i],sumC[i]为时间和系数的前缀和。如果将从j1到i的任务作为一批那么这一批的结束时间是sumT[i] S * (批次数)。这里批次数不好直接表示。一个经典技巧是“费用提前计算”。考虑当前批j1到i的启动时间S它会对本批及之后所有任务产生额外的费用。我们可以把S产生的费用提前加到当前决策中。转移方程dp[i] min{ dp[j] sumT[i]*(sumC[i]-sumC[j]) S*(sumC[n]-sumC[j]) }其中0 j i。变形dp[i] min{ dp[j] - (sumT[i]S)*sumC[j] } sumT[i]*sumC[i] S*sumC[n]。令y(j) dp[j],x(j) sumC[j],k(i) sumT[i] S。目标是最小化dp[j] - k(i)*sumC[j]即b y - k*x的最小值。注意这里k(i)是单调递增的因为sumT[i]递增x(j)也是单调递增的因为sumC[i]递增。直接套用下凸壳模板即可。例题2玩具装箱洛谷P3195题目描述略。其标准转移方程为dp[i] min{ dp[j] (i - j - 1 sum[i]-sum[j] - L)^2 }。 通过将sum[i]加上iL加上1令s[i] sum[i] i,L’ L 1可以转化为dp[i] min{ dp[j] (s[i] - s[j] - L’)^2 }。 展开后变形为dp[i] s[i]^2 min{ (dp[j] s[j]^2 2*L’*s[j]) - 2*s[i]*s[j] } (s[i]^2 L’^2 2*s[i]*L’)。 令y(j) dp[j] s[j]^2 2*L’*s[j],x(j) s[j],k(i) 2*s[i]。又回到了标准形式。实操心得遇到复杂式子不要慌。核心步骤永远是1) 写出原始DP方程2) 将min/max括号内关于i和j的项分离特别是把含有i*j交叉项的系数整理出来3) 将与j相关的部分通常是dp[j]和一些只含j的表达式视为y将与j相关且与i相乘的项中的j的部分视为xi的系数视为斜率k4) 检查x和k的单调性决定维护凸壳的方式。7. 边界条件、陷阱与调试技巧即使理解了原理实现时也容易踩坑。下面是我总结的几个常见陷阱1. 队列初始化问题通常需要将初始状态比如j0加入队列。务必确保这个初始点的x,y计算正确并且dp[0]的值符合题目定义。有时dp[0]可能不为0。2. 斜率比较的等号问题在维护凸壳队尾弹出时如果遇到三点共线的情况即slope(j1, j2) slope(j2, j3)是否需要弹出j2对于求最小值下凸壳通常需要弹出。因为中间的j2点对于后续任何斜率都不会成为最优决策它被两端的点“支配”了保留它只会让凸壳多一个点增加不必要的判断。所以在slope_check函数中我们使用而非。对于求最大值上凸壳同理使用。3. 除零与溢出除零在计算斜率时如果x坐标可能相等直接除法会导致除零错误。这就是为什么必须用交叉相乘来比较斜率的原因。交叉相乘完美避免了除法。溢出y和x可能很大做乘法时(y2-y1)*(x3-x2)很可能超出int范围。务必使用long long。在极端情况下甚至可能需要__int128或手写高精度比较。4. 单调性假设不成立怎么办如果斜率k(i)不是单调的我们就不能用单调队列在O(1)内弹出队首了。此时有两种主流方法二分查找在凸壳仍然用队列/数组维护上二分查找第一个斜率大于k(i)的位置。复杂度 O(n log n)。CDQ分治更通用的方法可以处理x(j)和k(i)都不单调的情况。其思想是“离线”处理通过分治将动态插入点和查询的过程转化为静态问题。复杂度也是 O(n log n)。5. 调试技巧打印队列状态在每次循环中打印出队列里的点下标j以及计算出的x(j), y(j)。手动画图看看这些点是否真的构成了一个凸壳。对拍写一个 O(n²) 的暴力DP用小数据n1000随机生成大量测试用例比较两种方法的结果是否一致。这是最可靠的调试方法。检查变形最怕的是变形公式推错了。可以随机固定一个i和几个j分别用原始公式和变形后的y - k*x公式计算值看是否只差一个常数。8. 从一次翻车案例看思维闭环最后分享一个我印象深刻的翻车案例。当时做一道题转移方程是dp[i] max{ a[i]*b[j] c[j] }其中a[i]单调递减b[j]单调递增。我一看这形式很像y kx b啊ka[i],xb[j],yc[j]。于是兴冲冲地开始维护凸壳。结果一直WA。排查了很久才发现问题我要求的是最大值。对于直线y kx b给定斜率k找最大截距b。这等价于b y - kx的最大值。而我之前维护的是下凸壳求最小值时用的。对于最大值应该维护上凸壳斜率单调递减。修正方法在维护队尾凸壳性质时将slope_check的不等号从改为。在维护队首时因为k(i)即a[i]是单调递减的所以最优决策点会向左移动。判断条件需要从“斜率小于等于当前k”弹出改为“斜率大于等于当前k”弹出。这个案例给我的教训是永远明确目标是求min还是max。求min对应最小化截距维护下凸壳求max对应最大化截距维护上凸壳。明确k(i)和x(j)的单调性。这决定了维护队首是用单调队列O(1)弹出还是二分查找O(log n)。推导时最好把变形后的式子写成b y - kx的形式。这样目标是最小化/最大化b几何意义非常清晰就是用过点(x, y)、斜率为k的直线的截距。斜率优化本质上是一种数学建模和数据结构优化的结合。它要求我们先把问题抽象成合适的DP模型然后通过代数变形发现其几何本质最后用合适的数据结构单调队列/栈、二分、平衡树来加速查询。这个过程锻炼的不仅是编码能力更是分析和转化的思维能力。多练习几种典型模型总结出自己的变形套路和代码模板再遇到这类问题时你就能一眼看穿本质快速写出正确的代码。

相关新闻

Navicat数据库管理工具:从连接配置到高级功能实战指南

Navicat数据库管理工具:从连接配置到高级功能实战指南

1. 从零到一:为什么Navicat是数据库管理的“瑞士军刀” 如果你刚接触数据库,或者一直用命令行和MySQL打交道,那么第一次打开Navicat的感觉,大概就像从手动挡汽车换到了智能电动车。命令行固然强大、精准,但对于日常的数…

2026/10/13 14:45:50 阅读更多 →
手游数值修改实战:从内存原理到GameGuardian工具应用

手游数值修改实战:从内存原理到GameGuardian工具应用

在手游开发或逆向分析的学习过程中,理解游戏数值的存储与修改机制是一个经典的实践课题。它不仅能帮助我们深入理解内存、数据加密等底层原理,也是学习移动应用安全、游戏逻辑分析的重要一步。本文将以一款名为“动物战争模拟器”的手游(版本…

2026/10/9 18:20:11 阅读更多 →
数据分析进阶——解读用户画像精细化运营【附全文阅读】

数据分析进阶——解读用户画像精细化运营【附全文阅读】

【CSDN 618年中狂欢群友专属】 �� 错过等一年!两大王炸福利同时炸场: 【CSDN官方福利】 �� 福利① 会员大促 • VIP年卡:买1年送1年 → 低至3.5折 • 加赠:618次下载 0元秒杀 每…

2026/10/10 1:19:37 阅读更多 →

最新新闻

黑胶唱片旋转效果:用requestAnimationFrame实现高精度匀速转动

黑胶唱片旋转效果:用requestAnimationFrame实现高精度匀速转动

1. 项目概述:用代码“转”出一张会呼吸的黑胶唱片你有没有盯着老式唱机上那张缓缓旋转的黑胶唱片发过呆?不是为了听歌,而是被那种沉稳、连续、带着轻微震颤的物理转动本身吸引——指针划过沟槽的微响、唱片边缘泛起的柔光、转盘轴承里藏着的精…

2026/10/13 15:32:14 阅读更多 →
C++迭代器模式详解:从设计原理到自定义实现与避坑指南

C++迭代器模式详解:从设计原理到自定义实现与避坑指南

1. 迭代器模式到底解决了什么问题1.1 算法与容器解耦&#xff1a;一份代码&#xff0c;处处能跑先抛个问题&#xff1a;你写的std::sort既能排std::vector<int>&#xff0c;又能排std::deque<double>&#xff0c;还能排原生数组&#xff0c;凭什么&#xff1f;要是…

2026/10/13 15:32:14 阅读更多 →
工业互联网数字化工厂方案:从车间痛点讲到投资回报

工业互联网数字化工厂方案:从车间痛点讲到投资回报

今年年中&#xff0c;有家做精密机加工的企业找到我&#xff0c;让我帮忙整理一套工业互联网智能制造数字化工厂解决方案&#xff0c;说是要拿去跟集团管理层做年度汇报。我们第一版PPT做得挺“全”&#xff0c;云平台、数据中台、AI质检、数字孪生&#xff0c;能想到的概念全放…

2026/10/13 15:32:14 阅读更多 →
MATLAB信号处理实战指南:从FFT频谱分析到滤波器设计源码解析

MATLAB信号处理实战指南:从FFT频谱分析到滤波器设计源码解析

简介&#xff1a;沈再阳老师的“MATLAB信号处理”课件与源码&#xff0c;是一套面向信号处理学习者与相关开发者的实用资料&#xff0c;内容结合了MATLAB基础操作与信号处理核心理论&#xff0c;系统讲解傅里叶变换、数字滤波器设计、频谱分析、采样定理等关键知识点。压缩包内…

2026/10/13 15:32:14 阅读更多 →
MSCNN人群密度估计数据集制作全流程指南

MSCNN人群密度估计数据集制作全流程指南

1. 项目概述&#xff1a;为什么人群密度估计需要专门制作数据集&#xff0c;而不是直接用现成图像&#xff1f;“基于MSCNN的人群密度估计之数据集制作”——这个标题里藏着三个关键动作&#xff1a;“MSCNN”是模型架构&#xff0c;“人群密度估计”是任务目标&#xff0c;“数…

2026/10/13 15:32:14 阅读更多 →
刀具磨损预测全流程:从传感器信号到在线预警

刀具磨损预测全流程:从传感器信号到在线预警

简介&#xff1a;这是一份面向机械加工与智能制造领域的刀具磨损预测项目&#xff0c;适合有一定机器学习基础、希望将深度学习与群智能优化算法结合到工业场景的学习者。资源覆盖从数据读取、清洗、特征构建到模型训练与预测的完整流程&#xff0c;主体采用霜冰优化算法对卷积…

2026/10/13 15:31:13 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/12 18:11:17 阅读更多 →