zoukankan      html  css  js  c++  java
  • P2120 [ZJOI2007]仓库建设

    (f_i) 表示在 (i) 工厂建立仓库,(i+1sim n-1) 工厂不建立仓库的最小总费用。对 (p) 做一遍前缀和。

    转移直接枚举上一个建立的工厂在哪儿:

    [f_i=min{f_j-(p_i-p_j) imes(x_n-x_i)+c_i|j<i} ]

    考虑两个决策 (j,k(j<k)),若 (j)(k) 优:

    [f_j-(p_i-p_j) imes(x_n-x_i)<f_k-(p_i-p_k) imes(x_n-x_i) ]

    [f_j-f_k<(x_n-x_i) imes(p_i-p_j-p_i+p_k) ]

    [dfrac{f_k-f_j}{p_k-p_j}>x_i-x_n ]

    因为 (x_i-x_n) 随着 (i) 的增大单调递增,所以维护一个下凸壳。

    时间复杂度 (Oleft(n ight))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define N 1000005
    #define Db double
    #define Min(x,y)((x)<(y)?x:y)
    #define For(i,x,y)for(i=x;i<=(y);i++)
    ll p[N],f[N];
    int x[N],c[N],que[N];
    int read()
    {
    	int A;
    	bool K;
    	char C;
    	C=A=K=0;
    	while(C<'0'||C>'9')K|=C=='-',C=getchar();
    	while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    	return(K?-A:A);
    }
    inline Db slope(int j,int k)
    {
    	return Db(f[k]-f[j])/Db(p[k]-p[j]);
    }
    int main()
    {
    	int n,i,head,tail;
    	n=read();
    	For(i,1,n)
    	{
    		x[i]=read(),p[i]=read(),c[i]=read();
    		f[0]-=p[i]*x[i];
    		p[i]+=p[i-1];
    	}
    	f[0]+=p[n]*x[n];
    	head=tail=1;
    	For(i,1,n-1)
    	{
    		while(head<tail&&slope(que[head],que[head+1])<=x[i]-x[n])head++;
    		f[i]=f[que[head]]-(p[i]-p[que[head]])*(x[n]-x[i])+c[i];
    		/*cout<<i<<' '<<f[i]<<' '<<que[head]<<endl;*/
    		while(head<tail&&slope(que[tail-1],que[tail])>=slope(que[tail],i))tail--;
    		que[++tail]=i;
    	}
    	For(i,1,n-1)f[0]=Min(f[0],f[i]);
    	cout<<f[0]+c[n];
    	return 0;
    }
    
  • 相关阅读:
    WinForm里保存TreeView状态
    动态规划 回溯和较难题
    go 基本链表操作
    leetcode 42接雨水
    leetcode 旋转数组搜索
    leetcode 牛客编程 子序列 树 数组(积累)
    剑指offer(积累)
    go快排计算最小k个数和第k大的数
    leetcode 打家劫舍
    leetcode 字符串相关问题
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14247120.html
Copyright © 2011-2022 走看看