zoukankan      html  css  js  c++  java
  • P2900 [USACO08MAR]Land Acquisition G

    题目描述

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

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

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

    题解

    很容易想到如果一块土地的长和宽都比另一块小,那么这两块土地合并一下并按照大的那块土地计算比分开计算优。

    所以我们先将土地按照长度从小到大排序,再对它们的高度维护一个单调递减栈,最后在栈中的土地才是有意义的。

    对于这些土地,我们进行(dp),设(f[i])表示考虑到第(i)块土地的最小费用,状态转移方程(f[i] = min(f[i], f[j] + h[j + 1] * l[i])[1 leq j < i])
    ,这个转移过程是(O(n ^2))的,显然不可行。

    所以我们考虑斜率优化,假设(1leq k < j < i),且对于(i)来说,(j)(k)优,那么

    (f[j] + h[j + 1] * l[i] leq f[k] + h[k + 1] * l[i])

    (f[j] - f[k] leq (h[k + 1] - h[j + 1]) * l[i])

    (frac{f[j] - f[k]}{- h[j + 1] - (- h[k + 1])} leq l[i])

    所以以此为判断条件弹出不优的队首并依次更新即可。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define int long long
    using namespace std;
    const int N = 50005;
    int n, top, sta[N], q[N], l, r;
    ll f[N];
    struct node{int x, y;}a[N], b[N];
    inline int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    bool cmp(const node & a, const node & b) {return a.x < b.x;}
    int X(int i) {return - b[i + 1].y;}
    ll Y(int i) {return f[i];}
    double slope(int i, int j) {return (double)(Y(i) - Y(j)) / (double)(X(i) - X(j));}
    void work()
    {
    	n = read();
    	for(int i = 1; i <= n; i ++) {a[i].x = read(); a[i].y = read();}
    	sort(a + 1, a + n + 1, cmp);
    	for(int i = 1; i <= n; i ++)
    	{
    		while(top && a[sta[top]].y <= a[i].y) top --;
    		sta[++ top] = i;
    	}
    	for(int i = 1; i <= top; i ++) b[i] = a[sta[i]];
    	q[l = r = 1] = 0;
    	for(int i = 1; i <= top; i ++)
    	{
    		while(l < r && slope(q[l], q[l + 1]) <= b[i].x) l ++;
    		f[i] = f[q[l]] + (ll)b[q[l] + 1].y * b[i].x;
    		while(l < r && slope(q[r - 1], q[r]) >= slope(q[r - 1], i)) r --;
    		q[++ r] = i;
    	}
    	printf("%lld
    ", f[top]);//top
    }
    signed main() {return work(), 0; }
    
  • 相关阅读:
    Jenkins配置:添加用户和管理权限
    Jenkins安装与配置
    jenkins配置邮件通知
    Jenkins 配置邮件通知
    jenkins+SVN配置
    第九周学习进度
    梦断代码阅读笔记 01
    第八周学习进度
    “理了么”软件特点NABCD个人分析
    第七周学习进度
  • 原文地址:https://www.cnblogs.com/Sunny-r/p/12610906.html
Copyright © 2011-2022 走看看