• [Usaco2008 Mar]土地购买 斜率优化DP


    以为是智商题,想了一天

    试着把矩形去重后保留了单调减的长和单调增的宽,推出了一个DP转移方程,

    猜是和满足单峰性质试着三分写了一发wa了,果然不是单峰性质的

    之后感觉转移方程像一次函数就想到维护凸包,试探性地搜了关键字usaco和斜率优化发现这题果然是。。

    然后就学了学斜率优化DP

    自己推出来直线的性质还是比较好理解的

    每个矩形都可以看做一个一次函数,长为斜率,dp值为高

    主要就是转移反应在两条直线的交点左右两侧不同,始终选在下面那段线段转移过来是最优的,

    这就要求在加入直线的时候始终保持变动点坐标的单调递增

    如果新的变动点比之前某个变动点坐标小,画画图会发现弹掉一条之前的直线会有更好的下段线段供转移

     1 //#include<bits/stdc++.h>  
     2 //#pragma comment(linker, "/STACK:1024000000,1024000000")   
     3 #include<stdio.h>  
     4 #include<algorithm>  
     5 #include<queue>  
     6 #include<string.h>  
     7 #include<iostream>  
     8 #include<math.h>                    
     9 #include<stack>
    10 #include<set>  
    11 #include<map>  
    12 #include<vector>  
    13 #include<iomanip> 
    14 #include<bitset>
    15 
    16 using namespace std;         //
    17 
    18 #define ll long long  
    19 #define ull unsigned long long
    20 #define pb push_back  
    21 #define FOR(a) for(int i=1;i<=a;i++) 
    22 #define sqr(a) (a)*(a)
    23 #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
    24 ll qp(ll a,ll b,ll mod){
    25     ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
    26 }
    27 struct DOT{int x;int y;};
    28 inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} 
    29 void ex(){puts("-1");exit(0);}
    30 const int dx[4]={0,0,-1,1};
    31 const int dy[4]={1,-1,0,0};
    32 const int inf=0x3f3f3f3f; 
    33 const ll Linf=0x3f3f3f3f3f3f3f3fLL;
    34 const ll Mod=1e18+7;
    35 const double eps=1e-6;
    36 const double pi=acos(-1.0);
    37 
    38 const int maxn=5e4+33;
    39 
    40 int n;
    41 
    42 struct NODE{
    43     int x,y;
    44 }a[maxn];
    45 
    46 bool cmp(NODE lx,NODE rx){
    47         if(lx.x==rx.x)return lx.y>rx.y;
    48         return lx.x>rx.x;
    49 }
    50 
    51 ll dp[maxn];
    52 
    53 int q[maxn];
    54 
    55 double bias(int j,int k){    //k better j
    56     return (1.0*dp[j]-dp[k])/(1.0*a[k+1].x-a[j+1].x);
    57 }
    58 
    59 int main(){
    60     scanf("%d",&n);
    61     for(int i=1;i<=n;i++){
    62         scanf("%d%d",&a[i].x,&a[i].y);
    63     }
    64     sort(a+1,a+1+n,cmp);
    65     int tot=1;
    66     for(int i=2;i<=n;i++){
    67         if(a[i].x<=a[tot].x && a[i].y<=a[tot].y)continue;
    68         a[++tot]=a[i];
    69     }
    70     
    71     int l=0,r=0;
    72     for(int i=1;i<=tot;i++){
    73         while(l<r && bias(q[l],q[l+1])<a[i].y){
    74             l++;
    75         }
    76         dp[i]=dp[q[l]]+1ll*a[q[l]+1].x*a[i].y;
    77         while(l<r && bias(q[r-1],q[r])>bias(q[r],i)){
    78             r--;
    79         }
    80         q[++r]=i;
    81     }
    82 
    83     printf("%lld
    ",dp[tot]);
    84 }
    View Code
  • 相关阅读:
    C#设计模式学习笔记-单例模式
    面向对象的七种设计原则
    继承 示例1
    继承和多态的那些事
    体检套餐管理项目
    魔兽登录系统
    清空表
    mysql批量插入
    mkdir用大括号同时建立多个同级和下级目录
    linux查看机器位数
  • 原文地址:https://www.cnblogs.com/Drenight/p/8869870.html
Copyright © 2020-2023  润新知