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