zoukankan      html  css  js  c++  java
  • The Simplest Course About The Slope Optimization

    The Simplest Course About The Slope Optimization

    中国人戳这里

    As a beginner, I have not understood the Slope Optimization very, this blog is just for who is the same as me who is a beginner.

    Buck up a minute.··

    I will introduce what i what to say mainly using a classic problem.

    Original question

    HDU3507

    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. (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000)

    The means of the problem

    It give you a numerical array a1~an, and you can devide into substrings with the cost of M every substring.

    And you should pay the Summation of square of summation of every elements in each substring.

    Exactly Resolution

    First, think about if there n is less than 5000 instead of 500000, how will you solve this question.

    I think you can easily find that the operation is without aftereffect, so you can use dynamic programming.

    Define f[i] as the least cost of it when we have already do at the i-th number.

    And  we can Pretreatment an array named sum that sum[i] is means the summation of a1~ai

    The transformation equation is that f[i] = min(f[j] + (sum[i]-sum[j-1])2 + M) (j is from 1 to i)

    Ok, the normal way to find the j that make that the value of the polynomial least is by going through 1~i

    But, you will realize that it will take O(n2) to solve the problem. Apparently, it will break up the time limit of this problem.

    Ok, so we should use the slope optimization.

    The Slope Optimization

    Derivation of formula

    We define that k < j < i and we now are finding the f[i].

    From the polynomial that I wrote, we can infer that if (sum[i]-sum[k-1])2 + f[k] + M < (sum[i]-sum[j-1])+ f[j] + M we must transform the k instead of i;

    Then simplify the inequality, we get 

    2*sum[i]*(sum[j-1]-sum[k-1]) < f[j]-f[k]+sum[j-1]2-sum[k-1]2

    Divide the (sum[j-1]-sum[k-1])

    get: 

    2*sum[i] < (f[j]-f[k]+sum[j-1]2-sum[k-1]2) / (sum[j-1]-sum[k-1])

    The use of slope

    You may not be able to find any slope in that formula, but let's try define the g(x) = f[x]+sum[x-1]

    And that formula turns to g(j) - g(k) / sum[j-1]-sum[k-1].

    Ok, then try to image what it is like, now?

    Right, slope.

    Ok, create a ectangular coordinate system,

    To find the best point to transform, we will find the line that has slope that just greater  than 2*sum[i]

    optimization

    Appearently,this way will also break up the time limit.

    And, just think, the slope from f[i] to [n] of line that we choose must be monotonically increasing.

    So, we can create a convex hull  to find the line.

    Right, it's that picture.

    But why we can use the convex hull without omiting any answer.

    Because all the point between kj and ji, the slope of it will be less than kj or be bigger than ji.

    So, it clearly is not be the best choice.

    Last use a monotonic queue to maintain the convex hull.

    And following is the code.

    #include<bits/stdc++.h>
    using namespace std;
    int a[500101];
    int sum[500101];
    int que[500101];
    int dp[500101];
    bool cal(int ax,int ay,int bx,int by,int cx,int cy)
    {
        return (ax-bx)*(cy-by)>=(ay-by)*(cx-bx);
    }
    int gety(int x)
    {
        return dp[x-1]+sum[x-1]*sum[x-1];
    }
    int getx(int x)
    {
        return sum[x-1];
    }
    int get(int i,int ss)
    {
        return gety(i)-2*ss*getx(i);
    }
    int main()
    {
        int n,m;
     
        while(scanf("%d%d",&n,&m) != EOF)
        {
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            sum[i] = sum[i-1] +  a[i];
        }
        int head = 0,tail = -1;
        for (int i = 1;i <= n;i++)
        {
            while(head < tail && cal(getx(que[tail-1]),gety(que[tail-1]),getx(que[tail]),gety(que[tail]),getx(i),gety(i)))
            {
                tail--;
            }
            que[++tail] = i;
            while(head < tail && get(que[head],sum[i]) >= get(que[head+1],sum[i]))
            {
                head++;
            }  
            dp[i] = get(que[head],sum[i]) + m + sum[i]*sum[i];
        }
        printf("%d
    ",dp[n]);
        }
        return 0;  
    }
  • 相关阅读:
    数据取证任务
    VMware虚拟机重置密码
    pon(无源光纤网络)
    Gpon与Epon的区别
    DNS相关
    牛人博客收集
    值得细细品读的URL资源
    SQL注入
    IPSec方案部署(多业务场景)
    python专题-函数式编程
  • 原文地址:https://www.cnblogs.com/mzyy1001/p/11190817.html
Copyright © 2011-2022 走看看