zoukankan      html  css  js  c++  java
  • poj3926 parade (单调队列+dp)

    题意:有n行路,每行路被分成m段,每一段有长度和权值,要求从最下面一行走到最上面一行某个位置,可以从相邻两行的同一列交点往上走,并且在同一行走的长度要<=K,求走过的最大权值

    设f[i][j]为到第i行,第j个交点的最大值
    设sumvalue[i][j,k]为第i行从第j个交点到第k个交点经过道路的权值之和
    设sumtime[i][j,k]为第i行从第j个交点到第k个交点经过道路的长度之和
    则f[i][j]=max{
    f[i-1][k]+sumvalue[i][k,j] ,k<=j且sumtime[i][k,j]<=K
    f[i-1][k]+sumvalue[i][j,k] ,k>j且sumtime[i][j,k]<=K
    }

    以第一个方程为例,单调队列记某行i∈[k,j]的f[][i]+sumvalue[][i..j]的最大值即可

    其中,在j++的时候,由于要给所有数加上val[][j]的值,我们就假装大家一起
    减掉了val[][j]的值,只给要新进的f[][j]+val[][j]减掉sumvalue[][0..j]即可
    (最后给f值的时候别忘了加回来)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long int
     5 using namespace std;
     6 const int maxn=110,maxm=10010;
     7 
     8 int rd(){
     9     int x=0,neg=1;char c=getchar();
    10     while(c<'0'||c>'9') {if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 int N,M,K;
    16 int val[maxm][maxn],len[maxm][maxn],head,tail;
    17 LL f[maxm][maxn],q[maxm][2],ans;
    18 
    19 inline void insert(LL x,int y){
    20     for(int i=tail;i>=head;i--){
    21         if(q[i][0]>x){
    22             tail=i+1;q[tail][0]=x;q[tail][1]=y;
    23             return;
    24         }
    25     }tail=head;q[tail][0]=x;q[tail][1]=y;
    26 }
    27 
    28 int main(){
    29     int i,j,k;
    30     //freopen("3926.in","r",stdin);
    31     while(1){
    32         N=rd(),M=rd(),K=rd();if(!N) break;
    33         for(i=1;i<=N+1;i++){
    34             for(j=1;j<=M;j++) val[j][i]=rd();
    35         }for(i=1;i<=N+1;i++){
    36             for(j=1;j<=M;j++) len[j][i]=rd();
    37         }
    38         memset(f,0,sizeof(f));ans=0;
    39         for(i=1;i<=N+1;i++){
    40             LL sv=0,st=0;
    41             tail=head=1;memset(q,0,sizeof(q));
    42             for(j=0;j<=M;j++){
    43                 sv+=val[j][i],st+=len[j][i];
    44                 insert(f[j][i-1]-sv,st);
    45                 while(st-q[head][1]>K) head++;
    46                 f[j][i]=q[head][0]+sv;
    47             }
    48             sv=0;st=0;
    49             tail=head=1;memset(q,0,sizeof(q));
    50             for(j=M;j>=0;j--){
    51                 sv+=val[j+1][i],st+=len[j+1][i];
    52                 insert(f[j][i-1]-sv,st);
    53                 while(st-q[head][1]>K) head++;
    54                 f[j][i]=max(f[j][i],q[head][0]+sv);
    55             }
    56         }
    57         for(j=0;j<=M;j++) ans=max(ans,f[j][N+1]);
    58         printf("%d
    ",ans);
    59     }
    60     
    61 }
  • 相关阅读:
    hdu-5492 Find a path(dp)
    hdu-5493 Queue(二分+树状数组)
    bzoj-2243 2243: [SDOI2011]染色(树链剖分)
    codeforces 724
    codeforces 422A A. Borya and Hanabi(暴力)
    codeforces 442C C. Artem and Array(贪心)
    codeforces 442B B. Andrey and Problem(贪心)
    hdu-5918 Sequence I(kmp)
    poj-3739. Special Squares(二维前缀和)
    hdu-5927 Auxiliary Set(树形dp)
  • 原文地址:https://www.cnblogs.com/Ressed/p/9376995.html
Copyright © 2011-2022 走看看