您的位置:首页 > 运维架构

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).

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息