luogu2900 [USACO08MAR]土地征用Land Acquisition

http://www.elijahqi.win/archives/1334
题目描述
Farmer John is considering buying more land for the farm and has his eye on N (1 <= N <= 50,000) additional rectangular plots, each with integer dimensions (1 <= width_i <= 1,000,000; 1 <= length_i <= 1,000,000).

If FJ wants to buy a single piece of land, the cost is $1/square unit, but savings are available for large purchases. He can buy any number of plots of land for a price in dollars that is the width of the widest plot times the length of the longest plot. Of course, land plots cannot be rotated, i.e., if Farmer John buys a 3x5 plot and a 5x3 plot in a group, he will pay 5x5=25.

FJ wants to grow his farm as much as possible and desires all the plots of land. Being both clever and frugal, it dawns on him that he can purchase the land in successive groups, cleverly minimizing the total cost by grouping various plots that have advantageous width or length values.

Given the number of plots for sale and the dimensions of each, determine the minimum amount for which Farmer John can purchase all

约翰准备扩大他的农场,眼前他正在考虑购买N块长方形的土地。如果约翰单买一块土 地,价格就是土地的面积。但他可以选择并购一组土地,并购的价格为这些土地中最大的长 乘以最大的宽。比如约翰并购一块3 × 5和一块5 × 3的土地,他只需要支付5 × 5 = 25元, 比单买合算。 约翰希望买下所有的土地。他发现,将这些土地分成不同的小组来并购可以节省经费。 给定每份土地的尺寸,请你帮助他计算购买所有土地所需的最小费用。

输入输出格式
输入格式:

Line 1: A single integer: N
Lines 2..N+1: Line i+1 describes plot i with two space-separated integers: width_i and length_i
输出格式:

Line 1: The minimum amount necessary to buy all the plots.
输入输出样例
输入样例#1:

4
100 1
15 15
20 5
1 100
输出样例#1:

500
说明
There are four plots for sale with dimensions as shown.

The first group contains a 100x1 plot and costs 100. The next group contains a 1x100 plot and costs 100. The last group contains both the 20x5 plot and the 15x15 plot and costs 300. The total cost is 500, which is minimal.

一开始的题目,只是给我们n块随机的地,让我们分组,可以往的1D1D形式的dp一般都会要求每组中序号都是连续的,这样我们才可以进行dp。那此题怎么办呢?首先有个显然的优化:如果x1<=x2&&y1<=y2则(x1,y1)完全可以和(x2,y2)打包在一起购买而不用付出额外的花费,因此(x1,y1)就可以不再考虑了。所以我们把所有的地按x为第一关键字,y为第二关键字进行升序排序,把可以和别的地“打包”购买的都去掉。这之后我们发现,剩下的地有了特殊的性质:x[i]<=x[i+1],y[i]>=y[i+1]。即x是递增的,y是递减的。在这种情况下,我们便可以证明分组一定是连续的才会最优。(如果选择了i,i+2一组,而没有i+1,则不如把i+1也加入这组,因为x[i+1]<=x[i+2],y[i+1]<=y[i],i+1的加入完全不会造成额外的花费。)这样我们就可以进行dp了。f[i]表示购买前i块地所需的最少花费。则f[i]=min{f[j]+y[j+1]∗x[i]|0≤j

#include<cstdio>
#include<algorithm>
#define N 55000
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0;char ch=gc();
    while (ch<'0'||ch>'9') ch=gc();
    while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}
    return x;
}
struct node{
    int l,w;
}data[N];
long long f[N];int n,flag[N],q[N];
inline bool cmp(node a,node b){
    return a.l==b.l?a.w>b.w:a.l>b.l;
}
inline double slope(int k1,int k2){
    return 1.0*(f[k2]-f[k1])/(data[k1+1].l-data[k2+1].l);
}
int main(){
//    freopen("2900.in","r",stdin);
    n=read();
    for (int i=1;i<=n;++i) data[i].l=read(),data[i].w=read();
    sort(data+1,data+n+1,cmp);int maxl=0,maxw=0;
    for (int i=1;i<=n;++i) if(data[i].l<=maxl&&data[i].w<=maxw) flag[i]=1;else maxl=data[i].l,maxw=data[i].w;
    for (int i=1;i<=n;++i) if(flag[i]) data[i].l=data[i].w=0;
    sort(data+1,data+n+1,cmp);
    for (int i=1;i<=n;++i) if (!data[i].l&&!data[i].w){n=i-1;break;}
//    for (int i=1;i<=n;++i) printf("%d %d\n",data[i].l,data[i].w);
    int l=1,r=1;q[1]=0;
    for (int i=1;i<=n;++i){
        while (l<r&&slope(q[l],q[l+1])<data[i].w) ++l;int t=q[l];
        f[i]=f[t]+(long long)data[t+1].l*data[i].w;
        while(l<r&&slope(q[r-1],q[r])>slope(q[r],i)) --r;q[++r]=i;
    }
    printf("%lld",f[n]);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值