• HDU3507 print artical


    题目大意:有N个数字a[N],每输出连续的一串,它的费用是 “这行数字的平方加上一个常数M”。问如何输出使得总费用最小。(n<=500000)

    分析:动态规划方程为:dp[i]=dp[j]+M+(sum[i]-sum[j])^2;

    右边有一项为:sum[i]*sum[j]。考虑用单调队列。

    令dp[i]=g,dp[j]+M+sum[i]^2+sum[j]^2=y,sum[j]=y,2*sum[i]=k

    则上式变为g=y-kx,即y=kx+g。此为直线方程。

    我们要使得g最小,即可以考虑有一条斜率为k的直线自下向上平移,设它接触到的第一个点为(xp,yp),则p为最佳决策点,所以最佳决策点的集合构成了一个下凸包的形状。又因为斜率k是2*sum[i],随着i的递增,斜率k是递增的,所以凸包中的点具备单调性,可以使用单调队列来优化。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MAXN 500005
    int n,m,t,head,tail,arr[MAXN];
    int f[MAXN],sum[MAXN];
    int st[MAXN];
    bool turnleft(int i,int j,int k)
    {
        int y1=f[i]+sum[i]*sum[i]-f[j]-sum[j]*sum[j];
        int y2=f[j]+sum[j]*sum[j]-f[k]-sum[k]*sum[k];
        int x1=(sum[i]-sum[j]);
        int x2=(sum[j]-sum[k]);
        if(x2*y1>x1*y2)return 1;
        else return 0;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&arr[i]);
                sum[i]=sum[i-1]+arr[i];
            }
            f[0]=0;//arr[1]*arr[1]+m;
            head=tail=1;
            st[tail++]=0;
            for(int i=1;i<=n;i++)
            {
                int k;
                for(;head<tail-1;)
                {
                    if(f[st[head+1]]+sum[st[head+1]]*sum[st[head+1]]-f[st[head]]-sum[st[head]]*sum[st[head]]>2*sum[i]*(sum[st[head+1]]-sum[st[head]]))
                        break;
                    else head++;
                }
                k=st[head];
                f[i]=f[k]+(sum[i]-sum[k])*(sum[i]-sum[k])+m;
                    while(head<tail-1&&(turnleft(i,st[tail-1],st[tail-2])==0))
                    {
                        tail--;
                    }
                    st[tail++]=i;
                }
                printf("%d
    ",f[n]);
                memset(sum,0,sizeof sum);
                memset(f,0,sizeof f);
                memset(st,0,sizeof st);
            }
            return 0;
    }
    

      

  • 相关阅读:
    Red5/FMS视频直播带宽计算
    基于NPOI开源框架写的ExcelHelper
    Using C# 4.0 and dynamic to parse JSON
    跟我学MVVM模式开发
    supermap使用代码示例(GIS)
    使用OpenXML将Excel内容读取到DataTable中
    ADO 数据类型转换表
    I don't like Regex...
    将Datatable转Excel少于4笔时汉字乱码4/26
    记录宝宝成长脚印3/31
  • 原文地址:https://www.cnblogs.com/hefenghhhh/p/4593680.html
Copyright © 2020-2023  润新知