• hdu 3507 Print Article(斜率优化DP)


    题目链接:hdu 3507 Print Article

    题意:

    每个字有一个值,现在让你分成k段打印,每段打印需要消耗的值用那个公式计算,现在让你求最小值

    题解:

    设dp[i]表示前i个字符需要消耗的最小值,那么有dp[i]=min{dp[k]+(sum[i]-sum[k])2+m)}(k<i)。

    这样是n2 的做法。

    考虑用斜率优化:

    设k<j,对于dp[i],从k+1到i为一段比j+1到i为一段更优。

    那么有

    dp[j]+(sum[i]-sum[j])2+m<=dp[k]+(sum[i]-sum[k])2+m

    整理得:

    dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k])/sum[j]-sum[k]<=2*sum[i]。

    不等式的右边就是一个斜率,然后用单调队列优化,做到O(n)的复杂度。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;++i)
     3 using namespace std;
     4 
     5 const int N=5e6+7;
     6 int n,m,dp[N],sum[N],Q[N],head,tail;
     7 
     8 int getx(int j,int k){return sum[j]-sum[k];}
     9 int gety(int j,int k){return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];}
    10 int check(int i,int j,int k){return gety(i,j)*getx(j,k)<=gety(j,k)*getx(i,j);}
    11 
    12 int main()
    13 {
    14     while(~scanf("%d%d",&n,&m))
    15     {
    16         F(i,1,n)scanf("%d",sum+i),sum[i]+=sum[i-1];
    17         head=1,tail=0;
    18         Q[++tail]=0;
    19         F(i,1,n)
    20         {
    21             while(head<tail&&gety(Q[head+1],Q[head])<=2*sum[i]*getx(Q[head+1],Q[head]))head++;
    22             dp[i]=dp[Q[head]]+(sum[i]-sum[Q[head]])*(sum[i]-sum[Q[head]])+m;
    23             while(head<tail&&check(i,Q[tail],Q[tail-1]))tail--;
    24             Q[++tail]=i;
    25         }
    26         printf("%d
    ",dp[n]);
    27     }
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    Android中Handler的使用
    Android ListView使用
    Android ListView的XML属性
    Android ListView几个重要属性
    Android设置日期DatePickerDialog
    Android资源文件说明
    Android使用xml文件中的array资源
    Android:控件Spinner实现下拉列表
    如何搭建个人博客网站(Mac)
    SVProgressHUD源码解读(2.0.3)
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6150146.html
Copyright © 2020-2023  润新知