浅谈斜率优化 DP
由于作者去年 tg 都没一等,文中有错误请大家多多提出。
斜率优化是用来求解一系列 dp 方程形如
显然转移方程中
考虑把转移方程化简,得到
此时,根据一次函数定义,可以得到
通过观察以下图,可以发现中间的点
如果
模板
还是上式转移方程对应的代码,这里给出
int f[N],q[N];
int hh = 0,tt = -1;
q[++tt] = 0;
// 这里 Y (i),X (i),K (i) 就是上式中推出的式子中的 Y,X,k
double slope (int i,int j) {
return (Y (j) - Y (i)) / (X (j) - X (i));
}
for (int i = 1;i <= n;i++) {
while (hh < tt && slope (q[hh],q[hh + 1]) < K (i)) hh++;
f[i] = f[q[hh]] + a[i] + b[q[hh]] + x[i] * y[q[hh]]; //转移方程
while (hh < tt && slope (q[tt - 1],q[tt]) > slope (q[tt],i)) tt--;
q[++tt] = i;
}
P2120
这里不选取任务安排系列的题目原因是非斜率优化部分过于麻烦。
下文中
考虑列出暴力转移方程
展开,得到
继续化简得到
令
那么得到
展开并添加括号得到
令
注意到
下面给出核心代码:
LL Y (int i) {
return f[i] + g2[i];
}
LL X (int i) {
return g1[i];
}
LL K (int i) {
return x[i];
}
double slope (int i,int j) {
if (X (i) == X (j)) return Y (j) - Y (i) > 0 ? 9e18 : -9e18; // 特判斜率正负无穷大
return (Y (j) - Y (i)) / (X (j) - X (i));
}
x[++n] = 3e9; // 添加哨兵,这题数据比较恶心
for (int i = 1;i <= n;i++) g1[i] = g1[i - 1] + p[i],g2[i] = g2[i - 1] + p[i] * x[i];
int hh = 0,tt = -1;
q[++tt] = 0;
for (int i = 1;i <= n;i++) {
while (hh < tt && slope (q[hh],q[hh + 1]) < K (i)) hh++;
f[i] = f[q[hh]] + x[i] * (g1[i] - g1[q[hh]]) - (g2[i] - g2[q[hh]]) + c[i];
// cout << q[hh] << endl;
while (hh < tt && slope (q[tt - 1],q[tt]) > slope (q[tt],i)) tt--;
q[++tt] = i;
}
简单总结一下,我们对于上述类似的转移方程,我们设
这样就讲完了最最最模板的斜率优化了。
求个赞不过分吧 QaQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类