[Luogu P2900] [USACO08MAR]土地征用Land Acquisition

本文介绍了一个经典的算法问题——农场购地问题。问题的核心是如何通过合理分组购地以最小化总成本。文章提供了详细的解题思路,包括如何利用排序、动态规划及斜率优化等技巧实现高效求解。

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

题目描述

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.

解题分析

我们用wid(x)wid(x)len(x)len(x) 分别表示土地的宽和长很明显, 如果存在一块土地xx 和另一块土地y,使得wid(x)wid(y)wid(x)≥wid(y)len(x)len(y)len(x)≥len(y) 那么显然我们在买xx 时可以一并将y 买入。

所以我们可以将所有土地按lenlen 为第一关键字, widwid为第二关键字由大到小排序, 选取widwid更大的即可去掉干扰的土地。 同时这样处理后,土地的lenlen从大到小排列的同时widwid 从小到大递增。我们可以得到转移方程:

dp[i]=min(dp[j]+len[j+1]×wid[i])dp[i]=min(dp[j]+len[j+1]×wid[i])

发现这个算法是O(n2)O(n2)的, 显然跑不过50000的数据量。
我们考虑两个转移点jjk满足j<kj<k且从kk转移花费更小, 即:

dp[j]+len[j+1]×wid[i]<dp[k]+len[k+1]×wid[i]

移项后可得

wid[i]>dp[j]dp[k]len[k+1]len[j+1]wid[i]>dp[j]−dp[k]len[k+1]−len[j+1]

发现左边是个递增的常数, 而右边与ii无关,并且是一个斜率的形式,所以我们可以用斜率优化和单调队列来维护转移点。每次我们处理队首时, 持续将满足要求的(即队首的下一个点最优)的队首弹出队列, 直至到达最优。

处理队尾的时候, 如果发现队尾和其上一个转移点的斜率比加入点和队尾的斜率还大的时候, 如图:

旁边的ShadyPi大佬说为了维护单调队列的单调性才将C踢出队列, 但博主认为BC的斜率过大, 导致难以转移, 而如果能够转移至C wid[i]肯定已大到可以转移至E点获得更优解, 所以C点显然是废的, 不如直接转移至E点。 所以出现这种情况时直接将C踢出队列。

那么现在思路应该很清晰了, 上代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#define R register
#define W while
#define IN inline
#define gc getchar()
#define MX 50005
#define ll long long
#define db double
using namespace std;
ll ans, dp[MX];
int num, tot, que[MX], head, tail;
struct Land
{
    ll len, wid;
}land[MX], deal[MX];
IN bool operator < (const Land &x, const Land &y)
{return x.len == y.len ? x.wid > y.wid : x.len > y.len;}
template <class T>
IN void in(T &x)
{
    x = 0; R char c = gc;
    W (!isdigit(c)) c = gc;
    W (isdigit(c))
    {x = (x << 1) + (x << 3) + c - 48, c = gc;}
}
IN db slope(const int &a, const int &b)
{
    return (db)(dp[b] - dp[a]) / (db)(deal[a + 1].len - deal[b + 1].len);
}
int main(void)
{
    in(num);
    for (R int i = 1; i <= num; ++i)
    in(land[i].len), in(land[i].wid);
    sort (land + 1, land + 1 + num);
    for (R int i = 1; i <= num; ++i)
    {if(land[i].wid > deal[tot].wid) deal[++tot] = land[i];}
    for (R int i = 1; i <= tot; ++i)
    {
        W (head < tail && slope(que[head], que[head + 1]) <= deal[i].wid) head++;
        dp[i] = dp[que[head]] + deal[que[head] + 1].len * deal[i].wid;
        W (head < tail && slope(que[tail - 1], que[tail]) > slope(que[tail], i)) tail--;    
        que[++tail] = i;
    }
    printf("%lld", dp[tot]);
}
内容概要:该PPT详细介绍了企业架构设计的方法论,涵盖业务架构、数据架构、应用架构和技术架构四大核心模块。首先分析了企业架构现状,包括业务、数据、应用和技术四大架构的内容和关系,明确了企业架构设计的重要性。接着,阐述了新版企业架构总体框架(CSG-EAF 2.0)的形成过程,强调其融合了传统架构设计(TOGAF)和领域驱动设计(DDD)的优势,以适应数字化转型需求。业务架构部分通过梳理企业级和专业级价值流,细化业务能力、流程和对象,确保业务战略的有效落地。数据架构部分则遵循五大原则,确保数据的准确、一致和高效使用。应用架构方面,提出了分层解耦和服务化的设计原则,以提高灵活性和响应速度。最后,技术架构部分围绕技术框架、组件、平台和部署节点进行了详细设计,确保技术架构的稳定性和扩展性。 适合人群:适用于具有一定企业架构设计经验的IT架构师、项目经理和业务分析师,特别是那些希望深入了解如何将企业架构设计与数字化转型相结合的专业人士。 使用场景及目标:①帮助企业和组织梳理业务流程,优化业务能力,实现战略目标;②指导数据管理和应用开发,确保数据的一致性和应用的高效性;③为技术选型和系统部署提供科学依据,确保技术架构的稳定性和扩展性。 阅读建议:此资源内容详尽,涵盖企业架构设计的各个方面。建议读者在学习过程中,结合实际案例进行理解和实践,重点关注各架构模块之间的关联和协同,以便更好地应用于实际工作中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值