斜率优化动态规划 学习笔记
首先看这样一个问题:
洛谷 P3195 [HNOI2008]玩具装箱
题目大意:
有 个物品排成一行,第 个物品权值为 ,现要求将这些物品分成若干段,每段的花费为 (其中 , 为这一段的左右端点, 为给定常数),问最小的总花费.保证 ,, .
这题显然是一道 DP 题. 令 为考虑前 个物品的最小代价, , 可以想出这样的状态转移方程:
然而, 如果暴力转移时间复杂度是 的, 显然会T, 有什么办法优化吗?
动态规划优化的一个重要思路是把可能决策的范围缩小 (即排除不可能的决策) . 顺着这个思路试试看?
首先我们观察状态转移方程, 发现这个 函数很碍事, 把它去掉:
这个方程太长了, 所以考虑令 , , 代入得:
这个平方也很碍事, 把它展开:
把跟 有关的移到等号一边, 跟 (读作"勾") 有关的放到另一边:
......感觉直到现在我们做的都是一些很常规的操作...... 但是如果我们放一个直线的表达式跟它对比一下?
于是我们惊奇地发现, 状态转移方程竟然可以看作一条斜率为 , 截距为 的直线和一个在 的点(我管它叫决策点)!
所以, "转移" 这个过程就可以理解为找到一个斜率为 的直线交于一个已有的决策点.
其中, 红色直线表示 对应的直线,绿色直线表示一个可能的 对应的直线, 点 A 表示这个 对应的决策点, 点 B 表示 对应的决策点.
所以我们怎么找一条最优的直线, 使得 最小? 难道要枚举 吗?
当然不用. 因为 只与 有关, 所以只要这条直线的截距最小, 就是最小的. 我们假设平面上已经有一堆可供转移的决策点和直线:
可以想象 对应的直线从下往上移动 (别忘了这条直线的斜率不变) , 显然它第一个接触到的点就是最优决策点.
如果您学过计算几何 (我没学过QAQ) , 您可以马上发现潜在的最优决策点都在这一堆点的下凸包上!
所以我们只需要用一个单调队列来维护这个凸包就可以了.
具体怎么维护等到以后再写罢, 博主累了.
综上所述, 我们通过发掘状态转移方程的性质做到了摊还 的转移, 非常优秀.
代码:
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
#define int ll
const int MAXN=50000;
int n,L,c[MAXN+5],sum[MAXN+5],dp[MAXN+5];
deque<int> q;
int a(int i){return sum[i]+i;}
int b(int i){return sum[i]+i+L+1;}
int X(int i){return b(i);}
int Y(int i){return (dp[i])+(b(i)*b(i));}
double slope(int i,int j){return double(Y(i)-Y(j))/double(X(i)-X(j));}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>L;
for(int i=1;i<=n;i++){
cin>>c[i];sum[i]=sum[i-1]+c[i];
}
q.push_back(0);
for(int i=1;i<=n;i++){
double qwq=114514.1919810;
if(q.size()>=2)qwq=slope(q[0],q[1]);
while(q.size()>=2&&slope(q[0],q[1])<double(2*a(i))){
q.pop_front();
}
int j=q.front();
dp[i]=dp[j]+(a(i)-b(j))*(a(i)-b(j));
while(q.size()>=2&&slope(q[q.size()-1],q[q.size()-2])>slope(q[q.size()-2],i))q.pop_back();
q.push_back(i);
}
cout<<dp[n]<<endl;
return 0;
}
本文作者:ztx-,使用署名-非商业性使用 4.0 国际进行许可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)