【Usaco Mar08 Gold】土地购买

本文介绍了一种利用斜率优化动态规划方法解决土地最优购买策略的问题。通过将土地按照长度排序,并确保宽度递减,实现了有效的状态转移方程。文章详细解析了解题思路与实现代码。

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

时间限制 : 10000 MS 空间限制 : 65536 KB

问题描述

农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <=1,000,000; 1 <= 长 <= 1,000,000).
每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要付5x5=25.
FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.

输入格式

  • 第1行: 一个数: N
  • 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽

输出格式

  • 第一行: 最小的可行费用.

样例输入

4
100 1
15 15
20 5
1 100

样例输出

500

提示

输入解释: 共有4块土地.

输出解释: FJ分3组买这些土地: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15.每组的价格分别为100,100,300, 总共500.

题解

其实我是知道了这是一道斜率优化题才开始做的……
第一眼是按长排序后再套个RMQ什么的,结果发现值是变化的,就没有写了。然后试着把宽也搞得单调一下,结果发现规律:当aiajbibjai≤aj⋀bi≤bj时(ii小于ja,ba,b表示长和宽),ii肯定与其他土地一起买且对结果不影响,所以我们可以把i从队列中删去,不予以讨论。最后的队列肯定是以长递增、以宽递减的序列。那么状态转移方程就显然了:

f[i]=min(f[j]+a[i]b[j+1])f[i]=min(f[j]+a[i]∗b[j+1])
最后用斜率优化即可。
好像在删除多余项时各大佬用了一种单调队列的方法,我只会系统unique()unique()……

代码

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pll;
const int maxn=5e4+5;
ll n,l,r,f[maxn],q[maxn];
pll a[maxn];
db slope(ll x,ll y)
{
    return (db)(f[y]-f[x])/(db)(a[x+1].second-a[y+1].second);
}
int main()
{
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++) scanf("%lld%lld",&a[i].first,&a[i].second);
    sort(a+1,a+1+n);
    for(ll i=n;i>1;i--)
        if(a[i].second>a[i-1].second) a[i-1]=a[i];
    n=unique(a+1,a+1+n)-a-1;
    for(ll i=1;i<=n;i++)
    {
        while(l<r&&slope(q[l],q[l+1])<(db)a[i].first) l++;
        ll j=q[l];
        f[i]=f[j]+a[i].first*a[j+1].second;
        while(l<r&&slope(q[r-1],q[r])>slope(q[r],i)) r--;
        q[++r]=i;
    }
    printf("%lld\n",f[n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值