• poj1821 Fence(单调队列优化dp)


    地址

    一排N个木板,M个工匠站在不同位置$S_i$,每个人可以粉刷覆盖他位置的、最长长度为$L_i$木板段,每刷一个有$P_i$报酬。同一木板只刷一次。求最大报酬。


    根据每个人的位置dp,设$f[i][j]$为第$i$个人刷前$j$个木板的最大报酬。$j<s[i]$表示不刷。

    那就有

    $f[i][j]=max{f[i-1][k]+(j-k)*p[i]}   $       $   (s[i]≤j<s[i]+L[i] , s[i]-L[i]≤k<j)$

    然后对于每行,相当于j从前面$l[i]$块选。拆开来。

    $f[i][j]=max{f[i-1][k]-k*p[i]}+j*p[i]  $       $   (s[i]≤j<s[i]+L[i] , s[i]-L[i]≤k<j)$

    然后里面跟决策点k有关,在每行$s[i]$前面$l[i]$个位置把决策塞进一个$f[i-1][k]-k*p[i]$单调减,$k$单调增的单调队列里,然后每行取队头,及时排除、转移即可。

    代码写繁了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long ll;
     8 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
     9 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    10 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    11 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    12 template<typename T>inline T read(T&x){
    13     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    14     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    15 }
    16 const int N=35000+7;
    17 int f[2][N],q[N];
    18 struct hinanawitenshi{
    19     int p,l,s;
    20 }a[107];
    21 int n,m,tmp,l,r;
    22 inline char cmp(hinanawitenshi A,hinanawitenshi B){return A.s<B.s;}
    23 inline int F(int k,int i,int now){return f[now^1][k]-k*a[i].p;}
    24 
    25 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout);
    26     read(n),read(m);
    27     for(register int i=1;i<=m;++i)read(a[i].l),read(a[i].p),read(a[i].s);
    28     sort(a+1,a+m+1,cmp);
    29     for(register int i=1,now=1;i<=m;++i,now^=1){
    30         tmp=0;l=1,r=0;
    31         for(register int j=1;j<a[i].s;++j)f[now][j]=f[now^1][j];
    32         for(register int k=_max(a[i].s-a[i].l,0);k<a[i].s;++k){
    33             while(l<=r&&F(k,i,now)>=F(q[r],i,now))--r;
    34             q[++r]=k;
    35         }
    36         for(register int j=a[i].s;j<=_min(a[i].s+a[i].l-1,n);++j){
    37             while(l<=r&&q[l]<j-a[i].l)++l;
    38             f[now][j]=_max(f[now^1][j],F(q[l],i,now^1)+j*a[i].p);
    39             MAX(tmp,f[now][j]);
    40         }
    41         for(register int j=a[i].s+a[i].l;j<=n;++j)f[now][j]=_max(f[now^1][j],tmp);//MISTAKE:之后的状态忘转移了。
    42     }
    43     printf("%d
    ",f[m&1][n]);
    44     return 0;
    45 }
  • 相关阅读:
    产品开发管理之流程和体系(总篇)
    .NET Core工程编译事件$(TargetDir)变量为空引发的思考
    EF Core新增迁移时无法加载程序集“System.ValueTuple”的错误
    Magicodes.Admin.Core开源框架总体介绍
    在WIN SERVER 2016上安装DOCKER(带过坑)
    使用NPOI生成Excel级联列表
    使用批处理根据项目工程文件生成Nuget包并发布(支持.NET Core)
    C#反射
    Oracle创建库
    深入了解MyBatis参数
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10453352.html
Copyright © 2020-2023  润新知