• HDU 3507 Print Article


    HDU 3507 Print 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

      这也算是一道经典的斜率优化题目,转移方程很好写:
     
    f[i] = min{f[j] + pow2(sum[i]-sum[j])} + m;
      带入不等式,发现若j<k,而j优于k,则
     
    f[j] + pow2(sum[i]-sum[j]) < f[k] + pow2(sum[i]-sum[k])
      这便意味着
     
    f[j] + pow2(sum[j]) - 2*sum[i]*sum[j] < f[k] + pow2(sum[k]) - 2*sum[i]*sum[k]
      所以
     
    f[j] + pow2(sum[j]) - (f[k] + pow2(sum[k]) ) <   2*sum[i] *(sum[j]- sum[k])
     
    f[k] + pow2(sum[k])  - (f[j] + pow2(sum[j]) ) <   2*sum[i] *(sum[k]- sum[j])
     
      斜率就出来了。因为sum[i]单调递增,而sum[k]- sum[j]恒正(这是最关键的一点),所以一旦队首(之前的最优解)比后面的不优,即
     
    f[k] + pow2(sum[j]) - (f[j] + pow2(sum[j]) ) >=   2*sum[i] *(sum[j]- sum[k])
      
      那么这个不等式便从此恒成立了。此时,我们就可以把队首清除。
     
      因为这是一个单调队列,所以同时可以清楚的判断出,应该是上凸还是下凸(此处是下凸)。
     
      但为什么是下凸呢?因为夹在中间的上凸点,显然比两边都不优。比左边不优很好说明,因为
      
      这道题目根本不成问题,套路见下。
     

    #define PN ""
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <utility>
    template<class T> inline void readin(T &res) {
        static char ch;T f=1;
        while((ch=getchar())<'0'||ch>'9')if(ch=='-')f=-1;
        res=ch-48;
        while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;
    }
    template<typename T>inline T max(T a,T b){if(a>b)return a;return b;}
    template<typename T>inline T min(T a,T b){if(a<b)return a;return b;}
    template<typename T>inline T abs(T a){if(a<0)return -a;return a;}
    
    typedef long long LL;
    
    const int N = 500000 + 100;
    class quque{
    private:
        LL list[N];
        int head, tail;
    public:
        quque():head(0),tail(0){}
        void clear(){head=tail=0;}
        void push(LL x){list[tail++]=x;}
        void pop(){++head;}
        void del(){--tail;}
        LL& operator[](LL pos){return list[head+pos];}
        LL size(){return tail-head;}
    }q;
    LL n, m, f[N], sum[N];
    
    inline LL pow2(LL x){return x*x;}
    inline LL UP(LL j,LL k) {return f[k]+pow2(sum[k])-f[j]-pow2(sum[j]);}
    inline LL DOWN(LL j,LL k) {return sum[k]-sum[j];}
    inline bool check1(LL j, LL k, LL i){return UP(j,k)<=2*sum[i]*DOWN(j,k);}
    inline bool check2(LL j,LL k,LL i) {return UP(j,k)*DOWN(k,i)>=UP(k,i)*DOWN(j,k);}
    
    
    int main() {
        //freopen(PN ".in","r",stdin);
        //freopen(PN ".out","w",stdout);
    while(~scanf("%lld%lld",&n,&m)) {
        sum[0]=0;
        for( LL i = 1; i <= n; i++ ) readin(sum[i]), sum[i]+=sum[i-1];
        q.clear();
        q.push(0);
        f[0] = 0;//All the first 0
        for( LL i = 1; i <= n; i++ ){
            while(q.size()>1 && check1(q[0],q[1],i)) q.pop();//队首后移直到最佳决策点(size>=2才可后移), 
            LL j=q[0];
            f[i]=f[j]+pow2(sum[i]-sum[j])+m;//决策转移
            while(q.size()>1 && check2(q[q.size()-2],q[q.size()-1],i)) q.del();//Graham-Scan式更新(size>=2才可删点) 
            q.push(i);//插入
        }
        printf("%lld
    ",f[n]);
    }
        return 0;
    }
    斜率优化
     
     
  • 相关阅读:
    Arduino uno 教程~持续更新~
    Arduino uno LED灯实验
    Arduino uno 引脚说明
    面包板的使用
    数量经济学推荐的Julia教程
    已知一点经纬度和距离,方位角;求另外一点的经纬度
    a recipe kindly provided by Dimas for kikuchi
    发现了拯救“文献多的一团麻”的工具
    matlab中diff的用法
    matlabR2017安装
  • 原文地址:https://www.cnblogs.com/Doggu/p/hdu3507.html
Copyright © 2020-2023  润新知