【[NOI2005]瑰麗華爾茲】
阿新 • • 發佈:2019-01-01
非常無腦和碼農的單調佇列優化\(dp\)
我們發現一個時間段內移動的情況是一樣的,而時間段的數目又非常少,所以可以直接按照時間段來進行\(dp\)
由於每一次\(dp\)的移動距離都是小於等於某一個固定值的,於是可以直接上單調佇列優化
複雜度\(O(nmk)\)
程式碼
#include<iostream> #include<cstring> #include<cstdio> #define re register #define maxn 205 #define max(a,b) ((a)>(b)?(a):(b)) int dp[maxn][maxn],now[maxn][maxn]; int n,m,sx,sy,K; int S,E,wind; char map[maxn][maxn]; int h,t,q[maxn]; inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } int main() { n=read(),m=read(),sx=read(),sy=read(),K=read(); for(re int i=1;i<=n;i++) scanf("%s",map[i]+1); memset(dp,-20,sizeof(dp)),memset(now,-20,sizeof(now)); now[sx][sy]=dp[sx][sy]=0; for(re int O=1;O<=K;O++) { S=read(),E=read(),wind=read(); int T=E-S+1; memset(now,-20,sizeof(now)); if(wind==4) { for(re int i=1;i<=n;i++) { h=1,t=0; memset(q,0,sizeof(q)); for(re int j=2;j<=m;j++) { while(h<=t&&dp[i][q[t]]-q[t]<dp[i][j-1]-j+1) t--; q[++t]=j-1; if(map[i][j-1]=='x') while(h<=t) h++; if(map[i][j]=='x') continue; while(h<=t&&q[h]+T<j) h++; if(h<=t) now[i][j]=max(dp[i][j],j+dp[i][q[h]]-q[h]); } } } if(wind==3) { for(re int i=1;i<=n;i++) { h=1,t=0; memset(q,0,sizeof(q)); for(re int j=m-1;j>=1;j--) { while(h<=t&&dp[i][q[t]]+q[t]<dp[i][j+1]+j+1) t--; q[++t]=j+1; if(map[i][j+1]=='x') while(h<=t) h++; if(map[i][j]=='x') continue; while(h<=t&&j+T<q[h]) h++; if(h<=t) now[i][j]=max(dp[i][j],dp[i][q[h]]+q[h]-j); } } } if(wind==2) { for(re int j=1;j<=m;j++) { h=1,t=0; memset(q,0,sizeof(q)); for(re int i=2;i<=n;i++) { while(h<=t&&dp[q[t]][j]-q[t]<dp[i-1][j]-i+1) t--; q[++t]=i-1; if(map[i-1][j]=='x') while(h<=t) h++; if(map[i][j]=='x') continue; while(h<=t&&q[h]+T<i) h++; if(h<=t) now[i][j]=max(dp[i][j],i+dp[q[h]][j]-q[h]); } } } if(wind==1) { for(re int j=1;j<=m;j++) { h=1,t=0; for(re int i=n-1;i>=1;i--) { while(h<=t&&dp[q[t]][j]+q[t]<dp[i+1][j]+i+1) t--; q[++t]=i+1; if(map[i+1][j]=='x') while(h<=t) h++; if(map[i][j]=='x') continue; while(h<=t&&i+T<q[h]) h++; if(h<=t) now[i][j]=max(dp[i][j],dp[q[h]][j]+q[h]-i); } } } for(re int i=1;i<=n;i++) for(re int j=1;j<=m;j++) dp[i][j]=max(dp[i][j],now[i][j]); } int ans=0; for(re int i=1;i<=n;i++) for(re int j=1;j<=m;j++) ans=max(ans,dp[i][j]); std::cout<<ans; return 0; }