luogu2900 购买土地

题目描述

Farmer John 准备扩大他的农场,眼前他正在考虑购买 N 块长方形的土地。

如果 FJ 单买一块土地,价格就是土地的面积。但他可以选择并购一组土地,并购的价格为这些土地中最大的长乘以最大的宽。比如 FJ 并购一块 3×5 和一块 5×3 的土地,他只需要支付 5×5=25 元, 比单买合算。

FJ 希望买下所有的土地。他发现,将这些土地分成不同的小组来并购可以节省经费。 给定每份土地的尺寸,请你帮助他计算购买所有土地所需的最小费用。

输入格式

第一行一个整数 N1N5×10^4)。

接下来 N 行,每行两个整数 w_i 和 l_i,代表第 i 块土地的长和宽。保证土地的长和宽不超过 10^6

输出格式

输出买下所有土地的最小费用。

输入输出样例

输入 #1
4 
100 1 
15 15 
20 5 
1 100 
输出 #1
500 

说明/提示

将所有土地分为三组:

  • 第一块土地为第一组,花费 100×1=100;
  • 第二,三块土地为第二组,花费 20×15=300;
  • 第四块土地为第三组,花费 1×100=100;

总花费为 500,可以证明不存在更优的方案。

________________________________________

简单的斜率优化动态规划

首先,如果一块的长宽都大于等于另一块地,那么另一块地是不需要交钱的。所以先把所有的土地按照长从大到小排序,如果后面的土地的宽度小于前面某块大的,则不需考虑。

剩余的土地的宽逐步减小,而长逐渐增加的(减小的都不用考虑)。

建立简单的动态规划:f[i]=min(f[j]+h[i]*w[j+1])

这个动归要依次从大到小枚举i,而每个i要枚举j,所以明显是O(N^2),无法完成。

由于出现了h[i]*w[j+1],而求得是最小值,因此考虑斜率优化。

设:0<j<k<i,且k优于j

所以,f[j]+h[i]*w[j+1]>f[k]+h[i]*w[k+1]

移项可得:(f[k]-f[j])/(w[k+1]-w[j+1])>-h[i]

我们通过前面的排序可知:h[i]是逐渐变大的,所以-h[i]逐渐减小,具有单调性

然后就按照斜率优化做就可以了!

________________________________________

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5e4+10;
 4 struct node
 5 {
 6     long long w,h;
 7 }sz[maxn];
 8 int n;
 9 int q[maxn];
10 long long f[maxn];
11 bool cmp(node a,node b)
12 {
13     return a.w>b.w || a.w==b.w &&a.h>b.h;
14 }
15 long double y(int a)
16 {
17     return (double)f[a];
18 }
19 long double x(int a)
20 {
21     return (double)sz[a+1].w;
22 }
23 long double get_xl(int a,int b)
24 {
25     return (y(b)-y(a))/(x(b)-x(a));    
26 }
27 
28 int main()
29 {
30     scanf("%d",&n);
31     for(int i=1;i<=n;++i)
32         scanf("%lld%lld",&sz[i].w,&sz[i].h);
33     sort(sz+1,sz+1+n,cmp);
34     int nn=1;
35     for(int i=2;i<=n;++i)
36         if(sz[i].h>sz[nn].h)sz[++nn]=sz[i];
37     int l,r;
38     l=r=0;
39     for(int i=1;i<=nn;++i)
40     {
41         while(l<r && get_xl(q[l],q[l+1])>=-sz[i].h)l++;
42         f[i]=f[q[l]]+sz[i].h*sz[q[l]+1].w;
43         while(l<r && get_xl(q[r-1],q[r])<=get_xl(q[r],i))--r;
44         q[++r]=i;
45     }
46     cout<<f[nn]<<endl;
47     return 0;
48 }
View Code

 

posted on 2021-02-01 15:03  gryzy  阅读(84)  评论(0编辑  收藏  举报

导航