HDU3507(dp + 斜率优化dp)

来源:互联网 发布:正规java培训班 编辑:程序博客网 时间:2024/05/16 12:21

Print Article

Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 12186 Accepted Submission(s): 3734

Problem Description
Zero has an old printer that doesn’t work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost

M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.

Input
There are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.

Output
A single number, meaning the mininum cost to print the article.

Sample Input
5 5
5
9
5
7
5

Sample Output
230

Author
Xnozero

Source
2010 ACM-ICPC Multi-University Training Contest(7)——Host by HIT

这是我做的第一道斜率优化dp的题目,目前优化dp的方法主流有两种,一种是用单调队列优化,另外一种是用斜率优化,其实我们后来发现,斜率优化过程中也用到了单调队列,两者共同的特点,也就是优化的原理是,通过具体的问题的特点,我们可以排除一些不够优的点,而保留更优的点,这个过程我们用单调队列实现就行。由于我只做了一道题,对斜率优化的理解也不是特别深,在这里我就说这么多。

#include<bits/stdc++.h>using namespace std;const int maxn = 1e6 + 10;//int inf = 1e9;int N, M;int sum[maxn];int dp[maxn];int q[maxn];int tail, head;int getY(int i){    return (dp[i] + sum[i] * sum[i]);}int getX(int i){    return 2 * sum[i];}int main(){    while(~scanf("%d%d", &N, &M))    {        int x;        sum[0] = 0;        for(int i = 1; i <= N; i++)        {            scanf("%d", &x);            sum[i] = sum[i - 1] + x;        }        dp[0] = 0;        tail = 1;        head = 0;        q[++head] = 0;        for(int i = 1; i <= N; i++)        {            while(head - tail >= 1 && (getY(q[tail + 1]) - getY(q[tail])) <= sum[i] * (getX(q[tail + 1]) - getX(q[tail]))) tail++;            //cout<<"tail == "<<tail<<endl;           // printf("q[tail] == %d\n", q[tail]);            dp[i] = dp[q[tail]] + (sum[i] - sum[q[tail]]) * (sum[i] - sum[q[tail]]) + M;            //printf("dp[%d] == %d\n", i, dp[i]);            if(tail >= head)            {                q[++head] = i;            }            else            {                while(head - tail >= 1)                {                    if((getY(i) - getY(q[head])) * (getX(q[head]) - getX(q[head - 1])) <= ((getY(q[head]) - getY(q[head - 1])) * (getX(i) - getX(q[head]))))                    {                        head--;                    }                    else break;                }                q[++head] = i;            }        }        printf("%d\n", dp[N]);    }    return 0;}