【斜率DP】bzoj1597: [Usaco2008 Mar]土地购买
1597: [Usaco2008 Mar]土地购买
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2474 Solved: 900
[Submit][Status][Discuss]
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
HINT
FJ分3组买这些土地: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15 plot. 每组的价格分别为100,100,300, 总共500
先按x,y递增排序。。
然后把那些可以被包含的土地删了
剩下的土地x递增y递减
然后转移方程f[i]=min(f[j]+y[j+1]*x[i]).
斜率方程(f[j]-f[k])/(y[k+1]-y[j+1])<x[i]
差不多了。。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 6 #define maxn 50001 7 8 using namespace std; 9 10 struct ed{ 11 int x,y; 12 }edge[maxn],E[maxn]; 13 14 long long f[maxn]; 15 16 double K(int x,int y){return (double)(f[y]-f[x])/(E[x+1].y-E[y+1].y);} 17 18 int que[maxn],n; 19 20 void DP() 21 { 22 int head=1,tail=1; 23 for(int i=1;i<=n;i++) 24 { 25 while(head<tail && K(que[head],que[head+1])<E[i].x)head++; 26 int sd=que[head]; 27 f[i]=f[sd]+(long long)E[sd+1].y*E[i].x; 28 while(head<tail && K(que[tail],i)<K(que[tail-1],que[tail]))tail--; 29 que[++tail]=i; 30 } 31 printf("%lld",f[n]); 32 } 33 34 bool cmp(const ed A,const ed B) 35 { 36 if(A.x==B.x)return A.y<B.y; 37 return A.x<B.x; 38 } 39 40 int main() 41 { 42 int b=0; 43 scanf("%d",&n); 44 for(int i=1;i<=n;i++) 45 scanf("%d%d",&edge[i].x,&edge[i].y); 46 sort(1+edge,1+edge+n,cmp); 47 for(int i=n;i>=2;i--) 48 { 49 if(edge[i].y>=edge[i-1].y) 50 { 51 swap(edge[i],edge[i-1]); 52 n--; 53 } 54 else swap(E[++b],edge[i]); 55 } 56 swap(E[++b],edge[1]); 57 sort(1+E,1+E+n,cmp); 58 DP(); 59 return 0; 60 }