bzoj 1597 土地购买
Description
农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <
= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价
格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要
付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.
Input
* 第1行: 一个数: N
* 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽
Output
* 第一行: 最小的可行费用.
Sample Input
4
100 1
15 15
20 5
1 100
输入解释:
共有4块土地.
100 1
15 15
20 5
1 100
输入解释:
共有4块土地.
Sample Output
500
FJ分3组买这些土地:
第一组:100x1,
第二组1x100,
第三组20x5 和 15x15 plot.
每组的价格分别为100,100,300, 总共500.
FJ分3组买这些土地:
第一组:100x1,
第二组1x100,
第三组20x5 和 15x15 plot.
每组的价格分别为100,100,300, 总共500.
HINT
思路 :这个题目是一个斜率优化的dp,我们先把初始的土地预处理一下,让土地的h递增,w递减,其他一些土地长宽都比某些土地小,这些土地是不会影响答案的。
然后我们设f[i]表示前i个土地的最小费用。
易证,f[i]=min(f[j]+h[i]*w[j+1]); 为了计算方便,将w数组错一位,f[i]=min(f[j]+h[i]*w[j]); 考虑两个转移f[j],f[k],且k<j<i ; 若对于f[i]从f[j]转移比从f[k]转移更优,那么f[j]+h[i]*w[j]<f[k]+h[i]*w[k];
根据线性规划的知识和斜率的知识,我们维护一个斜率不断减小的凸包,答案一定在凸包的点上。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 5 #define Rep(i,a,b) for(R i=a;i>=b;i--) 6 #define ms(i,a) memset(a,i,sizeof(a)) 7 #define gc() getchar() 8 #define LL long long 9 template<class T>void read(T &x){ 10 x=0; char c=0; 11 while (!isdigit(c)) c=gc(); 12 while (isdigit(c)) x=x*10+(c^48),c=gc(); 13 } 14 int const N=50000+3; 15 int q[N],n,st[N],top,m; 16 LL dp[N],h[N],w[N]; 17 struct node{ 18 int h,w; 19 bool operator < (const node &rhs) const{ 20 if(h!=rhs.h) return h<rhs.h; 21 return w>rhs.w; 22 } 23 }a[N]; 24 int main(){ 25 read(n); 26 rep(i,1,n) read(a[i].h),read(a[i].w); 27 sort(a+1,a+n+1); 28 st[top=1]=1; 29 rep(i,2,n)if(a[i].h!=a[i-1].h){ 30 while (top && a[i].w>=a[st[top]].w) top--; 31 st[++top]=i; 32 } 33 m=top; 34 w[0]=a[st[1]].w; 35 rep(i,1,m) h[i]=a[st[i]].h,w[i]=a[st[i+1]].w; 36 int st=0,ed=0; 37 rep(i,1,m){ 38 while (st<ed && dp[q[st+1]]-dp[q[st]]<h[i]*(w[q[st]]-w[q[st+1]])) st++; 39 dp[i]=dp[q[st]]+h[i]*w[q[st]]; 40 while (st<ed && (dp[i]-dp[q[ed]])*(w[q[ed]]-w[q[ed-1]])>(dp[q[ed]]-dp[q[ed-1]])*(w[i]-w[q[ed]])) ed--; 41 q[++ed]=i; 42 } 43 cout<<dp[m]<<endl; 44 return 0; 45 }