1 条题解

  • 0
    @ 2025-10-8 17:02:40
    /*
    这是100分的代码
    
    f[i]=min{ f[j ]+c[i]+s[i]-s[j ]-P[j ]*(L[i]-L[j ])  }
    
    f[i]-c[i]-s[i]   =   f[j ]-s[j ]+P[j ]*L[j]  -  P[j ]*L[i]
    
    f[j ]-s[j ]+P[j ]*L[j] = P[j ]*L[i]  +  f[i]-c[i]-s[i]
    yj= f[j ]-s[j ]+P[j ]*L[j]  
    k=L[i]
    x=P[j]
    b=f[i]-c[i]-s[i]
    题目希望f[i]小,所以希望b小,所以 维护队列下凸
    */ 
    
    #include<bits/stdc++.h>//100分的代码
    using namespace std;
    typedef long long LL;
    const int N=1e6+10; 
    LL f[N],L[N],p[N],P[N],c[N],s[N];
    int q[N];
    
    double X(int j){ return P[j]*1.0;}
    double Y(int j){ return 1.0*(f[j]-s[j]+P[j]*L[j]) ;}
    double slop(int j1,int j2){return (X(j2)==X(j1))?  1e18*(Y(j2)-Y(j1)) :  (Y(j2)-Y(j1))/(X(j2)-X(j1))  ;}
    
    int  main()
    {
        int n;scanf("%d",&n);
        L[0]=P[0]=s[0]=0;
        for(int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld%lld",&L[i],&p[i],&c[i]);
    		P[i]=P[i-1]+p[i];
    		s[i]=s[i-1]+P[i-1]*(L[i]-L[i-1]);//s[i]表示工厂1至工厂(i-1)的所有产品搬到工厂i的费用 
    	}
        
        int l=1,r=1;q[1]=0;f[0]=0;
        for(int i=1;i<=n;i++)
        {
        	while( l<r && slop( q[l] ,q[l+1] )<L[i]) l++;
        	f[i]= f[q[l]]+c[i]+s[i]-s[q[l]]-P[q[l]]*(L[i]-L[q[l]]);
    		while( l<r && slop(q[r-1],q[r])>slop(q[r],i) )r--;
    		q[++r]=i; 
        }
        while(p[n]==0 && n>0) n--;
        printf("%lld\n",f[n]);
        return  0;
    }
    /*
    
    #include<bits/stdc++.h>//30分的代码
    using namespace std;
    typedef long long LL;
    LL f[1110000],L[1110000],p[1110000],P[1110000],c[1110000];
      
    int  main()
    {
        int n;scanf("%d",&n);
        L[0]=P[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&L[i],&p[i],&c[i]);
            P[i]=P[i-1]+p[i];
        }
        f[0]=0;
        for(int i=1;i<=n;i++)
        {
            f[i]=f[i-1]+c[i];
            for(int j=i-1;j>=0;j--)
            {
                LL t=0;
                for(int k=j+1;k<=i-1;k++)
                {
                    t+=p[k]*(L[i]-L[k]);
                }
                f[i]=min(f[i],f[j]+c[i]+t);
            }
        }
        printf("%lld\n",f[n]);
        return  0;
    }
    
    #include<bits/stdc++.h>//50分的代码
    using namespace std;
    typedef long long LL;
    LL f[1110000],L[1110000],p[1110000],P[1110000],c[1110000],s[1110000];
     
    int  main()
    {
        int n;scanf("%d",&n);
        L[0]=P[0]=s[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&L[i],&p[i],&c[i]);
            P[i]=P[i-1]+p[i];
            s[i]=s[i-1]+P[i-1]*(L[i]-L[i-1]); 
        }
        f[0]=0;
        for(int i=1;i<=n;i++)
        {
            f[i]=f[i-1]+c[i];
            for(int j=i-1;j>=0;j--)
            {
                f[i]=min(f[i],f[j]+c[i]+s[i]-s[j]-P[j]*(L[i]-L[j])  );
            }
        }
        printf("%lld\n",f[n]);
        return  0;
    }
    */
    
    
    
    • 1

    *【斜率优化】[ZJOI2007] 仓库建设

    信息

    ID
    2749
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    递交数
    58
    已通过
    14
    上传者