P2900 [USACO08MAR] Land Acquisition G题解

题目描述

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

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

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

输入格式

第一行一个整数 N(1≤N≤5×104)。

接下来 N 行,每行两个整数 wi​ 和 li​,代表第 i 块土地的长和宽。保证土地的长和宽不超过 106。

输出格式

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

输入输出样例

输入 #1复制

4 
100 1 
15 15 
20 5 
1 100 

输出 #1复制

500 

说明/提示

将所有土地分为三组:

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

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

思路

首先,先打出暴力

代码:

#include<bits/stdc++.h>
using namespace std;
long long n,m=0,ma=0,f[50004];
struct one{
    long long x,y;
}a[50004],b[50004];
bool cmp(one a1,one b1){
    if(a1.x!=b1.x){
        return a1.x>b1.x;
    }
    else{
        return a1.y>b1.y;
    }
}
int main(){
	cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].y;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(ma<=a[i].y-1){
            b[++m]=a[i];
            ma=a[i].y;
        }
    }
    memset(f,62,sizeof(f));
    f[0]=0;
    for(int i=1;i<=m;i++){
        for(int j=0;j<=i-1;j++){
            if(f[j]+b[j+1].x*b[i].y<f[i]){
                f[i]=f[j]+b[j+1].x*b[i].y;
            }
            //f[i]=min(f[i],f[j]+b[j+1].x*b[i].y);
        }
    }
    cout<<f[m]<<endl;
	return 0;
}

然后,观察数据范围,直接卡常即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long n,m=0,ma=0,f[50004];
struct one{
    long long x,y;
}a[50004],b[50004];
bool cmp(one a1,one b1){
    if(a1.x!=b1.x){
        return a1.x>b1.x;
    }
    else{
        return a1.y>b1.y;
    }
}
int main(){
	cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].y;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(ma<=a[i].y-1){
            b[++m]=a[i];
            ma=a[i].y;
        }
    }
    memset(f,62,sizeof(f));
    f[0]=0;
    for(int i=1;i<=m;i++){
        for(int j=max(0,i-1-30000);j<=i-1;j++){
            if(f[j]+b[j+1].x*b[i].y<f[i]){
                f[i]=f[j]+b[j+1].x*b[i].y;
            }
            //f[i]=min(f[i],f[j]+b[j+1].x*b[i].y);
        }
    }
    cout<<f[m]<<endl;
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
long long n,m=0,ma=0,f[50004];
struct one{
    long long x,y;
}a[50004],b[50004];
bool cmp(one a1,one b1){
    if(a1.x!=b1.x){
        return a1.x>b1.x;
    }
    else{
        return a1.y>b1.y;
    }
}
int main(){
	cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].y;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(ma<=a[i].y-1){
            b[++m]=a[i];
            ma=a[i].y;
        }
    }
    memset(f,62,sizeof(f));
    f[0]=0;
    for(int i=1;i<=m;i++){
        for(int j=max(0,i-1-30000);j<=i-1;j++){
            if(f[j]+b[j+1].x*b[i].y<f[i]){
                f[i]=f[j]+b[j+1].x*b[i].y;
            }
            //f[i]=min(f[i],f[j]+b[j+1].x*b[i].y);
        }
    }
    cout<<f[m]<<endl;
	return 0;
}

posted @ 2025-10-24 15:26  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源