zoukankan      html  css  js  c++  java
  • BZOJ1597:[USACO]土地购买(斜率优化DP)

    Description

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

    Input

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

    Output

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

    Sample Input

    4
    100 1
    15 15
    20 5
    1 100
    输入解释:
    共有4块土地.

    Sample Output

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

    Solution

    若一个矩形可以被其他矩形覆盖,那么其实这个矩形是不需要考虑的。
    按x第一关键字,y第二关键字从小到大排序,单调栈就可以搞了。
    然后可以发现长为递增,宽为递减。
    就很容易发现是斜率优化了……p[i]为自变量,q[j+1]为斜率
    维护上凸,斜率优化

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define LL long long
     6 #define N (50000+100)
     7 using namespace std;
     8 struct node
     9 {
    10     LL x,y;
    11 }land[N];
    12 bool cmp(node a,node b) { return a.x<b.x || a.x==b.x && a.y<b.y; }
    13 
    14 LL p[N],q[N],cnt;
    15 LL Q[N*2],head,tail;
    16 LL f[N],n;
    17 
    18 LL K(LL j) { return q[j+1]; }
    19 LL B(LL j) { return f[j]; }
    20 LL Y(LL i,LL j) { return K(j)*p[i]+B(j); }
    21 
    22 LL cover(LL x1,LL x2,LL x3)
    23 {
    24     LL w1=(B(x1)-B(x2))*(K(x3)-K(x1));
    25     LL w2=(B(x1)-B(x3))*(K(x2)-K(x1));
    26     return w1<=w2;
    27 }
    28 
    29 int main()
    30 {
    31     scanf("%lld",&n);
    32     for (LL i=1;i<=n;++i)
    33         scanf("%lld%lld",&land[i].x,&land[i].y);
    34     sort(land+1,land+n+1,cmp);
    35     for (LL i=1;i<=n;++i)
    36     {
    37         while (cnt && land[i].y>=q[cnt]) cnt--;
    38         p[++cnt]=land[i].x; q[cnt]=land[i].y;
    39     }
    40     LL head=1,tail=1;
    41     for (LL i=1;i<=cnt;++i)
    42     {
    43         while (head<tail && Y(i,Q[head])>=Y(i,Q[head+1])) head++;
    44         f[i]=Y(i,Q[head]);
    45         while (head<tail && cover(i,Q[tail],Q[tail-1])) tail--;
    46         Q[++tail]=i;
    47     }
    48     printf("%lld",f[cnt]);    
    49 }
  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/refun/p/8680915.html
Copyright © 2011-2022 走看看