DP:斜率优化 Slope optimization
2014-02-16 15:13
260 查看
以HDU3507为例,讨论一下斜率优化问题。
http://acm.hdu.edu.cn/showproblem.php?pid=3507
题意:N个数字分段输出,输出每段(第i个到第j个)的代价是i到j的平方加上常数m,问输出所有N个数字的最小代价。
设dp[i]表示从第1个到第i个数字的代价,显然有dp[i] = min(dp[j] + (sum[i]-sum[j])^2 + m),时间复杂度O(N^2)。
设j<k<i,处理到第i个点时,如果k比j优,显然有dp[k]+(sum[i]-sum[k])^2+m < dp[j]+(sum[i]-sum[j])^2+m。
展开得到:g[j,k] = (dp[k]-dp[j]+sum[k]^2-sum[j]^2) / (2*(sum[k]-sum[j])) < sum[i],可以观察到斜率g[j,k]取值与i无关,因此可以用单调队列维护每次的最优解集:
1. 假设现在求完了dp[i],队列尾部两个元素依次是a,b(a<b<i),如果g[a, b] > g[b, i],则从队列中删除b点。
原因:如果g[b, i]<sum[i],则对于后面的点,i点比b点更优,删除b;如果g[a, b]>g[b, i]>sum[i],由于g[a, b] > sum[i],则对于后面的点,a点比b点更优,删除b。
2. 加入i点。
3. 假设现在要求dp[i+1],队列首部两个元素依次是a,b(a<b),如果g[a, b] <sum[i+1],b比a优,删除b。
4. 通过队头元素更新得等到dp[i+1]。
大体来说,是维持队列的下凸性质,删除多余的点。
时间复杂从而优化到O(N)。
In hdu3507, let's talk about slope optimization.
The problem asks you to print an article which has N words, and each word i has a cost Ci to be printed. Printing k words in one line will cost (∑Ci)^2+m. It wants the minimum cost in order to print the article.
Let dp[i] represents the cost from 1 to i-th, apparently it has dp[i] = min (dp[j] + (sum[i]-sum[j]) ^ 2 + m). The time complexity is O(N ^ 2).
Let j <k <i, , if k is more preferable than j when calculating dp[i], apparently it has dp[k] + (sum[i]-sum[k]) ^ 2 + m <dp[j] + (sum[i]-sum[j]) ^ 2 + m.
Then we get g[j,k] = (dp[k]-dp[j]+sum[k]^2-sum[j]^2) / (2*(sum[k]-sum[j])) < sum[i]. We find that the value of g[j, k] is not relevant to i, which means we can use monotonous queue to maintain the set of optimal solutions:
1. Assume we get dp[i], and the tail of the queue is a and b(a<b<i). If g[a, b]>b[b, i], then delete b from the queue.
Why? If g[b, i]<sum[i], then it means i is better than b thus delete b. If g[a, b]>g[b, i]>sum[i], it means g[a, b]>sum[i] thus a is better than b.
2. Add point i to the queue.
3. Now we will calculate dp[i+1]. Before that, if there are two top elements a and b(a<b) in the queue and g[a, b]<sum[i+1], i+1 will not update from a, then delete a.
4. Get dp[i+1] from top element of the queue.
Generally, slope optimization is to maintain the queue's downward convex property. It will avoid the calculation of extra points.
Thus optimizing the time complexity to O(N).
http://acm.hdu.edu.cn/showproblem.php?pid=3507
题意:N个数字分段输出,输出每段(第i个到第j个)的代价是i到j的平方加上常数m,问输出所有N个数字的最小代价。
设dp[i]表示从第1个到第i个数字的代价,显然有dp[i] = min(dp[j] + (sum[i]-sum[j])^2 + m),时间复杂度O(N^2)。
设j<k<i,处理到第i个点时,如果k比j优,显然有dp[k]+(sum[i]-sum[k])^2+m < dp[j]+(sum[i]-sum[j])^2+m。
展开得到:g[j,k] = (dp[k]-dp[j]+sum[k]^2-sum[j]^2) / (2*(sum[k]-sum[j])) < sum[i],可以观察到斜率g[j,k]取值与i无关,因此可以用单调队列维护每次的最优解集:
1. 假设现在求完了dp[i],队列尾部两个元素依次是a,b(a<b<i),如果g[a, b] > g[b, i],则从队列中删除b点。
原因:如果g[b, i]<sum[i],则对于后面的点,i点比b点更优,删除b;如果g[a, b]>g[b, i]>sum[i],由于g[a, b] > sum[i],则对于后面的点,a点比b点更优,删除b。
2. 加入i点。
3. 假设现在要求dp[i+1],队列首部两个元素依次是a,b(a<b),如果g[a, b] <sum[i+1],b比a优,删除b。
4. 通过队头元素更新得等到dp[i+1]。
大体来说,是维持队列的下凸性质,删除多余的点。
时间复杂从而优化到O(N)。
In hdu3507, let's talk about slope optimization.
The problem asks you to print an article which has N words, and each word i has a cost Ci to be printed. Printing k words in one line will cost (∑Ci)^2+m. It wants the minimum cost in order to print the article.
Let dp[i] represents the cost from 1 to i-th, apparently it has dp[i] = min (dp[j] + (sum[i]-sum[j]) ^ 2 + m). The time complexity is O(N ^ 2).
Let j <k <i, , if k is more preferable than j when calculating dp[i], apparently it has dp[k] + (sum[i]-sum[k]) ^ 2 + m <dp[j] + (sum[i]-sum[j]) ^ 2 + m.
Then we get g[j,k] = (dp[k]-dp[j]+sum[k]^2-sum[j]^2) / (2*(sum[k]-sum[j])) < sum[i]. We find that the value of g[j, k] is not relevant to i, which means we can use monotonous queue to maintain the set of optimal solutions:
1. Assume we get dp[i], and the tail of the queue is a and b(a<b<i). If g[a, b]>b[b, i], then delete b from the queue.
Why? If g[b, i]<sum[i], then it means i is better than b thus delete b. If g[a, b]>g[b, i]>sum[i], it means g[a, b]>sum[i] thus a is better than b.
2. Add point i to the queue.
3. Now we will calculate dp[i+1]. Before that, if there are two top elements a and b(a<b) in the queue and g[a, b]<sum[i+1], i+1 will not update from a, then delete a.
4. Get dp[i+1] from top element of the queue.
Generally, slope optimization is to maintain the queue's downward convex property. It will avoid the calculation of extra points.
Thus optimizing the time complexity to O(N).
int n,m,dp[500010],s[500010],q[500010],head,tail; int up(int j, int k) { return dp[k]-dp[j]+s[k]*s[k]-s[j]*s[j]; } int down(int j, int k) { return 2*(s[k]-s[j]); } int main() { while (~scanf("%d%d",&n,&m)) { for (int i=1;i<=n;i++) scanf("%d",&s[i]); for (int i=2;i<=n;i++) s[i] += s[i-1]; head = tail = 0; q[tail++] = 0; for (int i=1;i<=n;i++) { while (head+1<tail && up(q[head],q[head+1])<=s[i]*down(q[head],q[head+1])) head++; int j = q[head]; dp[i] = dp[j] + (s[i]-s[j])*(s[i]-s[j]) + m; while (head+1<tail && up(q[tail-1],i)*down(q[tail-2],q[tail-1])<=down(q[tail-1],i)*up(q[tail-2],q[tail-1])) tail--; q[tail++] = i; } printf("%d\n",dp ); } return 0; }
相关文章推荐
- 动易2006序列号破解算法公布
- C#数据结构与算法揭秘二
- 浅析STL中的常用算法
- JavaScript 组件之旅(二)编码实现和算法
- java数据结构和算法学习之汉诺塔示例
- python基础教程之python消息摘要算法使用示例
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- php的hash算法介绍
- 将15位身份证补全为18位身份证的算法示例详解
- C++算法系列之日历生成的算法代码
- 1 2 3 4 5 6 7 8 9 = 110的java实现
- Sedgewick之巨著《算法》,与高德纳TAOCP一脉相承
- 【代码】Pythonの代码片段
- STL中算法
- 数据结构&算法学习
- 算法的时间复杂度
- 算法导论:选择排序的原理与实现
- PHP实现四种常用的排序算法
- 图解插入排序算法