非常无脑和码农的单调队列优化(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;
}