BZOJ1597 USACO2008 土地并购

本文介绍了一种优化算法,用于解决Kano购买多块长方形土地的问题,通过并购策略减少总成本。文章提供了完整的代码实现及解析,展示了如何利用动态规划进行常数优化,达到O(n)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Description

Kano准备扩大他的农场,眼下必须购买N块长方形土地。如果Kano买一块土地,价格就是土地的面积。他也可以选择并购一块土地,并购的价格为这些土地中最大的长乘以最大的宽,比如Kano购买3x5和5x3的土地,只需要支付5x5=25元,比分开买合算。
请你帮他计算购买所有土地的最小费用。

Sample Input & Output

4
100 1
15 15
20 5
1 100

500


啊啊,先膜一下“水”大犇题目描述只是因为我把这题搬到自家oi上的


在写本题的 O(n2) 暴力dp的时候有没有想过常数优化?毕竟那些长宽小于某一块土地的都对答案没啥贡献,可以算是附赠的。而且如果在一维有序的情况下只需要理论下限的 O(n) 复杂度就可以过掉了。 那么此题的转移就很显然了:将两者都倒序枚举,除去干扰单调性的数据,则长单调递减,宽单调递增。可以得到转移方程:

dp[n]=mink=0n1{dp[k]+x[n]y[k+1]}
推出 g(i,j)
g(i,j)=dp[j]dp[i]y[i+1]y[j+1]

struct node{ 
    int h,w;
    bool operator < (const node &cmp)const{
        if(h!=cmp.h)return h>cmp.h;
        return w>cmp.w;
    }
}Base[M],Q[M];
int qtop=0;
int deq[M],L=0,R=-1;
long long dp[M]; 
long long up(int x,int y){return dp[y]-dp[x];} 
long long down(int x,int y){return Q[x+1].h-Q[y+1].h;} 
int main(){ 
    int n; 
    scanf("%d",&n); 
    for(int i=1;i<=n;i++) 
        scanf("%d %d",&Base[i].h,&Base[i].w);
    sort(Base+1,Base+n+1);
    int w=0;
    for(int i=1;i<=n;i++){
        if(Base[i].w<=w)continue;
        Q[++qtop]=Base[i];
        w=Base[i].w;
    } 
    n=qtop;
    deq[++R]=0;
    for(int i=1;i<=n;i++){
        while(L<R&&up(deq[L],deq[L+1])<Q[i].w*down(deq[L],deq[L+1]))++L;
        dp[i]=dp[deq[L]]+1LL*Q[deq[L]+1].h*Q[i].w;
        while(L<R&&up(deq[R-1],deq[R])*down(deq[R],i)>up(deq[R],i)*down(deq[R-1],deq[R]))--R; 
        deq[++R]=i;
    } 
    printf("%lld\n",dp[n]);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值