• hdu3507Print Article(斜率)


    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

    分析:
    第二道斜率优化,摸索出了一点套路

    说实话题目就看蒙了。。。
    题意:将序列a[n]分成若干段,每段的值为(∑a[i])^2 + M. 求序列的最小值

    做优化dp首先需要的就是状态转移方程

    f[i]表示到第i个数的最优值
    f[i]=min{f[j]+(sum[i]-sum[j])^2+m} (前一段最后一个数是j)

    假设 k < j < i
    f[j]的状态比k更优
    则一定有

    f[j]+(sum[i]-sum[j])^2+m < f[k]+(sum[i]-sum[k])^2+m
    f[j]+sum[j]^2-2*sum[i]*sum[j] < f[k]+sum[k]^2-2*sum[i]*sum[k]
    (f[j]+sum[j]^2)-(f[k]+sum[k]^2) < 2*sum[i]*(sum[j]-sum[k])
    移项,得

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

    设y=f[]+sum[]^2,x=sum[]
    则原式=>
    y[j]-y[k]/x[j]-x[k] < sum[i]
    设g(j,k)=y[j]-y[k]/x[j]-x[k]
    g(j,k) < sum[i]
    说明f[j]的状态比f[k]更优(横坐标更大的更优)

    那我们能不能利用这个性质去掉一些状态呢
    假设 k < j < i
    若g(j,k)>g(j,i),那么j这个状态可以去掉
    证明:
    1.g(i,j) < sum[i],i比j更优
    2.g(i,j) >=sum[i],则g(j,k)>g(i,j)>=sum[i],j比i优而k比j更优

    这样我们一旦遇到了g(j,k)>g(j,i)就可以去掉j这种状态了,

    这样我们的状态转移可以变成:
    1.维护一个双端优先队列
    2.维护f,在队首取元素,若g(q[tou],q[tou+1])<=sum[i],tou–
    因为tou+1的状态更优,直到g(q[tou],q[tou+1])>sum[i],
    就用q[tou]更新f
    3.在队尾加入f[i],若g(i,q[wei])<=g(q[wei],q[wei-1]),wei–,
    (g(j,k)>g(j,i)就可以去掉j这种状态了),直到g(i,q[wei])>g(q[wei],q[wei-1]),加入i

    tip:

    注意初始状态:
    f[0]=0;
    f[1]=sum[1]*sum[1]+m; //f[1]=f[0]+(sum[1]-sum[0])^2+m
    wei=1; tou=0; q[wei]=1; q[tou]=0;

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=500005;
    int n,m;
    int q[N],tou,wei,sum[N],f[N];
    
    double xl(int x,int y)
    {
        return (double)((f[x]+sum[x]*sum[x])-(f[y]+sum[y]*sum[y]))/(double)(2*f[x]-2*f[y]);
    }
    
    void doit()
    {
        f[0]=0; f[1]=sum[1]*sum[1]+m;  //初始状态很重要 
        wei=1; tou=0;
        q[wei]=1; q[tou]=0;
        for (int i=2;i<=n;i++)
        {
            while (tou<wei&&xl(q[tou],q[tou+1])<=sum[i]) tou++;
            f[i]=f[q[tou]]+(sum[i]-sum[q[tou]])*(sum[i]-sum[q[tou]])+m;
            while (tou<wei&&xl(i,q[wei])<=xl(q[wei],q[wei-1])) wei--;
            q[++wei]=i;
        }
        printf("%d",f[n]);
    }
    
    int main()
    {
        while (~(scanf("%d%d",&n,&m)))
        {
            int u;
            for (int i=1;i<=n;i++) scanf("%d",&u),sum[i]=sum[i-1]+u;
            doit();
        }
        return 0;
    }
  • 相关阅读:
    springMVC实现表单上传文件,MultipartResolver介绍及配置
    利用 java.util.Timer来写一个定时器
    集合泛型的不变性,而数组具有协变性,注意赋值容易导致的出错
    Python
    GenericServlet
    ServletRequest
    ServletConfig与ServletContext
    Servlet配置及生命周期
    使用jQuery实现Ajax
    XMLHttpRequest实现Ajax &数据格式JSON
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673491.html
Copyright © 2020-2023  润新知