标签:
锯木场选址(CEOI2004)
从山顶上到山底下沿着一条直线种植了n棵老树。当地的政府决定把他们砍下来。为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。
木材只能按照一个方向运输:朝山下运。山脚下有一个锯木厂。另外两个锯木厂将新修建在山路上。你必须决定在哪里修建两个锯木厂,使得传输的费用总和最小。假定运输每公斤木材每米需要一分钱。
任务
你的任务是写一个程序:
从标准输入读入树的个数和他们的重量与位置
计算最小运输费用
将计算结果输出到标准输出
输入
输入的第一行为一个正整数n——树的个数(2≤n≤20 000)。树从山顶到山脚按照1,2……n标号。接下来n行,每行有两个正整数(用空格分开)。第i+1行含有:wi——第i棵树的重量(公斤为单位)和 di——第i棵树和第i+1棵树之间的距离,1≤wi ≤10 000,0≤di≤10 000。最后一个数dn,表示第n棵树到山脚的锯木厂的距离。保证所有树运到山脚的锯木厂所需要的费用小于2000 000 000分。
输出
输出只有一行一个数:最小的运输费用。
样例
输入
9
1 2
2 1
3 3
1 1
3 2
1 6
2 1
1 2
1 1
输出
26
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=20010; 6 long long W[maxn],F[maxn],D[maxn],X[maxn]; 7 long long ans=2147483647; 8 int q[maxn],st,ed; 9 int main(){ 10 #ifndef ONLINE_JUDGE 11 freopen("two.in","r",stdin); 12 freopen("two.out","w",stdout); 13 #endif 14 int n; 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++){ 17 scanf("%lld%lld",&W[i],&D[i+1]); 18 W[i]+=W[i-1];D[i+1]+=D[i]; 19 X[i]=X[i-1]+(D[i]-D[i-1])*W[i-1]; 20 } 21 n+=1; 22 X[n]=X[n-1]+(D[n]-D[n-1])*W[n-1]; 23 q[st]=1; 24 for(int i=2;i<n;i++){ 25 while(st<ed){ 26 if(W[q[st+1]]*D[q[st+1]]-W[q[st]]*D[q[st]]<= 27 D[i]*(W[q[st+1]]-W[q[st]])) 28 st++; 29 else break; 30 } 31 ans=min(ans,X[n]+W[q[st]]*(D[q[st]]-D[i])+W[i]*(D[i]-D[n])); 32 while(st<ed){ 33 if((W[i]*D[i]-W[q[ed]]*D[q[ed]])*(W[q[ed]]-W[q[ed-1]])<= 34 (W[q[ed]]*D[q[ed]]-W[q[ed-1]]*D[q[ed-1]])*(W[i]-W[q[ed]])) 35 ed--; 36 else break; 37 } 38 q[++ed]=i; 39 } 40 printf("%lld\n",ans); 41 return 0; 42 }
标签:
原文地址:http://www.cnblogs.com/TenderRun/p/5553346.html