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 }
  • 相关阅读:
    03_ if 练习 _ little2big
    uva 11275 3D Triangles
    uva 12296 Pieces and Discs
    uvalive 3218 Find the Border
    uvalive 2797 Monster Trap
    uvalive 4992 Jungle Outpost
    uva 2218 Triathlon
    uvalive 3890 Most Distant Point from the Sea
    uvalive 4728 Squares
    uva 10256 The Great Divide
  • 原文地址:https://www.cnblogs.com/refun/p/8680915.html
Copyright © 2011-2022 走看看