zoukankan      html  css  js  c++  java
  • 斜率优化DP

    土地租用(加强版)

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 233  解决: 72
    [提交][状态][讨论版]

    题目描述

    随着YYHS的OI集训队人数急剧增加,原有的小机房已经容纳不了数量庞大的队员。 
    于是史老师决定租用一些实验室机位供队员们训练,他正在考虑为N (1 <= N <= 50,000)位队员租用机位。实验室管理员根据要求给出了N个机位的长和宽,每个机位的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 
    而机位的租用价格是它的面积,实验室管理员也提出,可以同时租用多个机位. 租用这一组机位的价格是它们最大的长乘以它们最大的宽, 但是机位的长宽不能交换. 如果想租下一个3x5的机位和一个5x3的机位,则他需要付5x5=25. 
    于是问题出现了,史老师希望租下所有的机位,但是他发现分组来租这些机位可以节省经费. 他需要你帮助他找到最小的经费. 

    输入

    * 第1行: 一个数: N 

    * 第2..N+1行: 每行包含两个数,分别为机位的长和宽 

    输出

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

    样例输入

    4
    100 1
    15 15
    20 5
    1 100
    

    样例输出

    500
    

    提示

    分3组租用这些机位: 第一组:100x1, 第二组1x100, 第三组20x5 和 15x15. 每组的价格分别为100,100,300, 总共500.
    见代码
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    #define maxn 50005
    long long f[maxn];
    struct note{
        ll x,y;
        friend bool operator <(note a,note b)
        {
            return(a.x==b.x&&a.y<b.y||a.x<b.x);
        }
    }a[maxn],b[maxn];
    ll n,cnt,Q[maxn];
    /*f[i]=min(f[j]+b[j+1].y*b[i].x)
    f[j]+b[j+1].y*b[i].x<f[k]+b[k+1].y*b[i].x
    f[j]-f[k]/(b[k+1].y-b[j+1].y)>b[i].x -->j is better than k
    because of b[i].x is getting larger
    g(i,j)>b[i].x mean i is better than j
    g(i,j)>g(j,k) :when g(i,j)>b[i].x i is better than j;else k is better than j ;so it's fobitted 
    */ 
    double Slope(ll j,ll k)
    {
        return (double)(f[j]-f[k])/(b[k+1].y-b[j+1].y);
     } 
    int main()
    {
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld %lld",&a[i].x,&a[i].y);
        }
        sort(a+1,a+1+n);
        for(ll i=1;i<=n;i++)
        {
            while(cnt&&a[i].y>=b[cnt].y) cnt--;
            b[++cnt]=a[i];
        }
        ll head,tail;
        head=tail=1;
        Q[1]=0;
        for(ll i=1;i<=cnt;i++)
        {
            while(head<tail&&Slope(Q[head],Q[head+1])<=b[i].x) head++;
            ll front=Q[head];
            f[i]=f[front]+b[i].x*b[front+1].y;
            while(head<tail&&Slope(Q[tail-1],Q[tail])>=Slope(Q[tail],i))tail--;
            Q[++tail]=i; 
        }    
        cout<<f[cnt]<<endl;
    }
  • 相关阅读:
    Oracle中的substr()函数和INSTR()函数和mysql中substring_index函数字符截取函数用法:计算BOM系数用量拼接字符串*计算值方法
    (转载)SDRAM驱动笔记
    【转】Verilog阻塞与非阻塞赋值使用要点
    【转转】(筆記) always block內省略else所代表的電路 (SOC) (Verilog)
    (原創) 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
    [转载]亚稳态
    Dev Exprss 发布部署
    Dev splliter 去除中间的分割显示
    DevTreeList中的新增、修改的设计
    Oracle 常用网址
  • 原文地址:https://www.cnblogs.com/dancer16/p/7533316.html
Copyright © 2011-2022 走看看