BZOJ 1597 Usaco 2008 Mar 土地购买 斜率优化DP

题目大意:给出一些木板,现在要购买这些木板。购买的规则是可以一些木板一起买,然后价格是最大的长度乘最大的宽度。求购买所有木板的最小费用。

思路:如果一个木板的长也比一个木板小,宽也比一个木板小,那么这个木板就可以被排除。把所有木板按照x的长度排序,然后去掉排除的木板,然后剩下的木板就是x值下降, y值上升的木板。这样的话我们买下连续的一段的费用就是x[j] * y[i],然后DP方程就很简单了:f[i] = f[j] - x[j + 1] * y[i]。

注意到数据范围,写一个斜率优化就水过了。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
using namespace std;

struct Complex{
    int x,y;
    bool blocked;

    bool operator <(const Complex &a)const {
        return x > a.x;
    }
    void Read() {
        scanf("%d%d",&x,&y);
    }
}src[MAX],point[MAX];

struct Point{
    long long x,y;

    Point(long long _ = 0,long long __ = 0):x(_),y(__) {}
}q[MAX];

int cnt,total;
long long f[MAX];
int front,tail;

inline double GetSlope(const Point &a,const Point &b)
{
    if(a.x == b.x)  return 1e15;
    return (double)(a.y - b.y) / (a.x - b.x);
}

inline void Insert(long long x,long long y)
{
    Point now(x,y);
    while(tail - front >= 2)
        if(GetSlope(q[tail],now) < GetSlope(q[tail - 1],q[tail]))
            --tail;
        else    break;
    q[++tail] = now;
}

inline Point GetAns(double slope)
{
    while(tail - front >= 2)
        if(GetSlope(q[front + 1],q[front + 2]) < slope)
            ++front;
        else    break;
    return q[front + 1];
}

int main()
{
    cin >> cnt;
    for(int i = 1; i <= cnt; ++i)
        src[i].Read();
    sort(src + 1,src + cnt + 1);
    int now = 0;
    for(int i = 1; i <= cnt; ++i) {
        if(src[i].y <= now)
            src[i].blocked = true;
        else    now = src[i].y;
    }
    for(int i = 1; i <= cnt; ++i)
        if(!src[i].blocked)
            point[++total] = src[i];
    for(int i = 1; i <= total; ++i) {
        Insert(-point[i].x,f[i - 1]);
        Point ans = GetAns(point[i].y);
        f[i] = ans.y - point[i].y * ans.x;
    }
    cout << f[total] << endl;
    return 0;
}

时间: 2024-08-01 04:15:53

BZOJ 1597 Usaco 2008 Mar 土地购买 斜率优化DP的相关文章

bzoj 1597 [Usaco2008 Mar]土地购买——斜率优化dp

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1597 又一道斜率优化dp.负数让我混乱.不过仔细想想还是好的. 还可以方便地把那个负号放到x上.只要改一下slope里的一个负号,就变成正常舒服的递增了. 这道题的要点其实是一开始h=0.不能h=1.这样就能把dp[0]纳入考虑.这是需要的. #include<iostream> #include<cstdio> #include<cstring> #includ

【bzoj 1597】[Usaco2008 Mar]土地购买

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

【BZOJ1597】【Usaco2008 Mar】土地购买 斜率优化DP

题解:首先将块排个序,然后去掉被其它某块包含的块,然后斜率优化dp dp方程:f[i]=f[j]+a[i]*b[j+1]; 具体什么x啊y啊什么的在代码注释里面. --....纠结死了.开始各种WA,现在才发现: inline long long xmul(Point i,Point j,Point k){(i.y-j.y)*(j.x-k.x)-(j.y-k.y)*(i.x-j.x);} 上面的代码竟然能通过编译--,无力吐槽.以后一定要用终端+Wall命令编译文件了. warning一日不死,

[USACO 2008 MAR] 土地购买

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1597 [算法] 首先将所有土地按长为第一关键字 , 宽为第二关键字排序 显然 , 当i > j , 且yi >= yj时 , 土地j没有用 , 不妨使用单调栈弹出所有没有用的土地 用fi表示前i块土地的最小经费 显然 , fi = min{ fj + aibj } 斜率优化即可 时间复杂度 : O(N) [代码] #include<bits/stdc++.h> usi

bzoj1597/luogu2900 土地购买 (斜率优化dp)

首先按x从小到大排序,那么可得: f[i]=min{f[j]+x[i]*maxy[j+1..i]} 然而这样是$O(n^2)$的而且无法做优化. 然后我们考虑:如果对于某一点,存在另一点的x和y都比它大,那这个点是可以删掉不参与计算的(因为那个较大的点一定要被买,那只要把这两点放在一组里,较小的点是绝对不会被算到的) 然后就可以发现,随着x[i]单调增,y[i]是单调减的 那刚才的式子就可以变成f[i]=min{f[j]+x[i]*y[j+1]}了,于是就可以做斜率优化了. 1 #include

BZOJ 1597 土地购买 斜率优化

首先,我们看啊,这道题是把线性序列分段的问题,于是显然需要用DP (^o^)/YES! 于是,f[i]就代表购买前i块土地所需要的最小费用 那么我们就来思考方程,但是发现可能需要我们先来排一排序,搞一搞就出来方程了 于是我们把length升序排列,放到一个队列中 这时我们发现有这样一种现象 存在land[i].length>=land[j].length&&land[i].width>=land[j].width那么j完全没有存在的必要(j表示我好伤心~~(>_<)

bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3191  Solved: 1450[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT Source [思路] 斜率优化. 设f[i]表示将前i个分组的最优值,则有转移方程式: f[i]=max{ f[j]

BZOJ 1617 Usaco 2008 Mar. River Crossing渡河问题

[题解] 显然是个DP题. 设$f[i]$表示送$i$头牛过河所需的最短时间,预处理出$t[i]$表示一次性送i头牛过河所需时间,那么我们可以得到转移方程:$f[i]=min(f[i],f[i-j]+t[j]+t[0])$ (这里的$t[0]$指的是FJ独自过河的时间) 这样就可以做一个$n$方的DP了 #include<cstdio> #include<algorithm> #define rg register #define inf (1e9) #define N (1000

[BZOJ 1010][HNOI2008]玩具装箱toy(斜率优化Dp)

Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压.缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过 压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容 器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一 个容器中,那么容器的长度将为 x=j-i+Sigma(Ck