Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化相关的知识,希望对你有一定的参考价值。

设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子

转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就中断

转移过程可以用单调非递增的双端队列优化

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 const int maxN=202;
  6 const int inf=0x3f3f3f3f;
  7 
  8 int dp[2][maxN][maxN];
  9 char map[maxN][maxN];
 10 int deqv[maxN];
 11 int deqn[maxN];
 12 int head,tail;
 13 int N,M,x,y,K;
 14 
 15 inline void resetDeq()
 16 {
 17     head=-1; tail=0;
 18 }
 19 
 20 inline void popDeq(int n,int len)
 21 {
 22     if(tail<head && n-deqn[tail]>len) ++tail;
 23 }
 24 
 25 inline void pushDeq(int v,int n)
 26 {
 27     while(head>=tail && v>deqv[head]) --head;
 28     deqv[++head]=v; deqn[head]=n;
 29 }
 30 
 31 inline int maxDeq()
 32 {
 33     if(head>=tail) return deqv[tail];
 34     else return -inf;
 35 }
 36 
 37 int main()
 38 {
 39     scanf("%d%d%d%d%d",&N,&M,&x,&y,&K);
 40     for(int i=1;i<=N;i++) scanf("%s",map[i]+1);
 41 
 42     memset(dp,0xc0,sizeof(dp));
 43     dp[0][x][y]=0;
 44 
 45     int s,t,dir;
 46     int len;
 47     while(K--)
 48     {
 49         scanf("%d%d%d",&s,&t,&dir);
 50         len=t-s+1;
 51 
 52         if(dir==4)
 53             for(int i=1;i<=N;i++)
 54             {
 55                 resetDeq();
 56                 for(int j=1;j<=M;j++)
 57                 {
 58                     if(map[i][j]==.)
 59                     {
 60                         popDeq(j,len);
 61                         dp[1][i][j]=std::max(dp[0][i][j],maxDeq()+j);
 62                         pushDeq(dp[0][i][j]-j,j);
 63                     }
 64                     else { resetDeq(); dp[1][i][j]=-inf; }
 65                 }
 66             }
 67         else if(dir==3)
 68             for(int i=1;i<=N;i++)
 69             {
 70                 resetDeq();
 71                 for(int j=M;j;j--)
 72                 {
 73                     if(map[i][j]==.)
 74                     {
 75                         popDeq(M-j,len);
 76                         dp[1][i][j]=std::max(dp[0][i][j],maxDeq()+M-j);
 77                         pushDeq(dp[0][i][j]-M+j,M-j);
 78                     }
 79                     else { resetDeq(); dp[1][i][j]=-inf; }
 80                 }
 81             }
 82         else if(dir==2)
 83             for(int j=1;j<=M;j++)
 84             {
 85                 resetDeq();
 86                 for(int i=1;i<=N;i++)
 87                 {
 88                     if(map[i][j]==.)
 89                     {
 90                         popDeq(i,len);
 91                         dp[1][i][j]=std::max(dp[0][i][j],maxDeq()+i);
 92                         pushDeq(dp[0][i][j]-i,i);
 93                     }
 94                     else { resetDeq(); dp[1][i][j]=-inf; }
 95                 }
 96             }
 97         else if(dir==1)
 98             for(int j=1;j<=M;j++)
 99             {
100                 resetDeq();
101                 for(int i=N;i;i--)
102                 {
103                     if(map[i][j]==.)
104                     {
105                         popDeq(N-i,len);
106                         dp[1][i][j]=std::max(dp[0][i][j],maxDeq()+N-i);
107                         pushDeq(dp[0][i][j]+i-N,N-i);
108                     }
109                     else { resetDeq(); dp[1][i][j]=-inf; }
110                 }
111             }
112         memcpy(dp[0],dp[1],sizeof(dp[1]));
113     }
114 
115     int ans=-inf;
116     for(int i=1;i<=N;i++)
117         for(int j=1;j<=M;j++)
118             ans=std::max(ans,dp[0][i][j]);
119     printf("%d\n",ans);
120     return 0;
121 }

 

以上是关于Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1499[NOI2005]瑰丽华尔兹 单调队列优化dp

luogu P2254 [NOI2005]瑰丽华尔兹

BZOJ1499[NOI2005]瑰丽华尔兹 单调队列+DP

[BZOJ1499][NOI2005]瑰丽华尔兹

BZOJ1499: [NOI2005]瑰丽华尔兹

●BZOJ 1499 [NOI2005]瑰丽华尔兹