E49 单调队列优化DP 瑰丽华尔兹

E49 单调队列优化DP 瑰丽华尔兹_哔哩哔哩_bilibili

 

P2254 [NOI2005] 瑰丽华尔兹 - 洛谷

// 单调队列 O(KNM)
#include<bits/stdc++.h>
using namespace std;

#define N 205
int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
char mp[N][N];
int n,m,sx,sy,K, ans,f[N][N];
struct node{int f,pos;} q[N]; //最长距离f,位置pos

//起点坐标x,y,行列长度L,时区长度tim,方向d
void DP(int x,int y,int L,int tim,int d){
  for(int i=1,h=1,t=0; i<=L; i++){
    if(mp[x][y]=='x') h=1,t=0; //遇到障碍,清空队列
    else{
      while(h<=t && q[h].pos<i-tim) h++;
      while(h<=t && q[t].f+i-q[t].pos<=f[x][y]) t--;
      q[++t]=node{f[x][y],i};
      f[x][y]=q[h].f+i-q[h].pos;
      ans=max(ans,f[x][y]);
    }
    x+=dx[d],y+=dy[d];
  }
}
int main(){
  scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&K);
  for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
  memset(f,-0x3f,sizeof(f)); f[sx][sy]=0;
  for(int k=1,s,t,d,tim;k<=K;k++){    //枚举k个时间区间
    scanf("%d%d%d",&s,&t,&d); tim=t-s+1;
    if(d==1) for(int i=1;i<=m;i++) DP(n,i,n,tim,d);//
    if(d==2) for(int i=1;i<=m;i++) DP(1,i,n,tim,d);//
    if(d==3) for(int i=1;i<=n;i++) DP(i,m,m,tim,d);//
    if(d==4) for(int i=1;i<=n;i++) DP(i,1,m,tim,d);//
  }
  printf("%d",ans);
}

 

posted @ 2023-04-29 14:18  董晓  阅读(362)  评论(0)    收藏  举报