• $Poj1821 Fence $单调队列优化$DP$


    Poj   Acwing

    Description

    有N块木板等待被M个工匠粉刷,每块木板至多被刷一次.第i个工匠要么不粉刷,要么粉刷包含木块Si的,长度不超过Li的连续的一段木板,每粉刷一块可以得到Pi的报酬.求如何安排能使工匠们获得的总报酬最多.

    1<=N<=16000,1<=M<=100

    Sol

    先把所有工匠按照Si从小到大排序,使我们能够按顺序进行线性Dp.

    设$F[i][j]$表示前i个工匠粉刷前j块木板的最大报酬(包含空着不刷的木板).转移分为三种情况:

    1.第i个工匠啥也不干 $F[i][j]=F[i-1][j]$

    2.第j块木板空着不刷 $F[i][j]=F[i][j-1]$

    3.第i个木匠刷k+1到j块木板 $F[i][j]=max(F[i-1][k]+Pi*(j-k)) (j-Li<=k<=Si-1,j>=Si)$

    然后用单调队列优化第3个式子

    $F[i][j]=Pi*j+max(F[i-1][k]-Pi*k)$ 单调队列维护$max(F[i-1][k]-Pi*k)$就OK了

    单调队列维护时元素的进出序列要弄清楚是队首还是队尾,不要搞混了 (大概也只有我会搞混 $ovo$

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<deque>
     4 #include<algorithm>
     5 #define il inline
     6 #define Rg register
     7 #define fr front
     8 #define bk back
     9 #define go(i,a,b) for(Rg int i=a;i<=b;i++)
    10 #define yes(i,a,b) for(Rg int i=a;i>=b;i++)
    11 using namespace std;
    12 il int read()
    13 {
    14     int x=0,y=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    17     return x*y;
    18 }
    19 int n,m,f[101][16001];
    20 deque<int>q;
    21 struct node{int l,p,s;}a[101];
    22 il int cal(int i,int x){return f[i-1][x]-a[i].p*x;}
    23 il bool cmp(node x,node y){return x.s<y.s;}
    24 int main()
    25 {
    26     n=read(),m=read();
    27     go(i,1,m)a[i]=(node){read(),read(),read()};
    28     sort(a+1,a+m+1,cmp);
    29     go(i,1,m)
    30     {
    31         q.clear();
    32         go(k,max(a[i].s-a[i].l,0),a[i].s-1)
    33         {
    34             while(q.size() && cal(i,q.bk())<=cal(i,k))q.pop_back();
    35             q.push_back(k);
    36         }
    37         go(j,1,n)
    38         {
    39             f[i][j]=max(f[i][j-1],f[i-1][j]);
    40             if(j>=a[i].s)
    41             {
    42                 while(q.size() && q.fr()<j-a[i].l)q.pop_front();
    43                     if(q.size())f[i][j]=max(f[i][j],a[i].p*j+cal(i,q.fr()));
    44             }
    45         }
    46     }
    47       printf("%d
    ",f[m][n]);
    48     return 0;
    49 }
    View Code

     

    光伴随的阴影
  • 相关阅读:
    eureka注册中心搭建
    MySQL基本查询语句
    通过IP地址和子网掩码与运算计算相关地址
    Linux bash 快捷键列表【转】
    Linux 系统简介【转】
    Linux Vim -d 比较两个文件
    无连接和面向连接协议的区别【转】
    ARP报文详解
    Linux 指定网卡 ping
    Linux Windows Java 快速生成指定大小的空文件
  • 原文地址:https://www.cnblogs.com/forward777/p/11248271.html
Copyright © 2020-2023  润新知