版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82597627
解析:
令
表示在第
个时间段后,停留在
时能够得到的最大滑行距离。
那么状态转移方程。我就不写了。。。代码里面很明白了。
而对于每一次更新,都是用的上一次的答案,所以按顺序更新可以直接省略第三维,节约空间。
而且每一次的更新也显然满足单调性。所以就直接上单调队列优化。
对于家具的位置,直接清空队列就行了,因为前后无法转移。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static
#define map Map
inline
ll getint(){
re ll num=0;
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;
while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
return f?-num:num;
}
inline
void outint(int a){
st char ch[13];
if(a==0)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
while(ch[0])pc(ch[ch[0]--]);
}
cs int INF=0x3f3f3f3f;
bool map[201][201];
int f[201][201];
int n,m,x,y,k;
int t[201],d[201];
int q[201],head,tail;
int num[201];
int main(){
n=getint();
m=getint();
x=getint();
y=getint();
k=getint();
memset(f,-INF,sizeof f);
f[x][y]=0;
for(int re i=1;i<=n;++i){
string s;
cin>>s;
for(int re j=1;j<=m;++j)if(s[j-1]=='x')map[i][j]=1;
}
for(int re i=1;i<=k;++i){
int a=getint(),b=getint();
t[i]=b-a+1,d[i]=getint();
}
for(int re kk=1;kk<=k;++kk){
switch(d[kk]){
case 1:{
for(int re j=1;j<=m;++j){
head=1;tail=0;
for(int re i=n;i>=1;--i){
if(map[i][j]){head=1;tail=0;continue;}
while(q[head]-i>t[kk]&&head<=tail)++head;
while((num[tail]<0||num[tail]+q[tail]-i<f[i][j])&&head<=tail)--tail;
q[++tail]=i;num[tail]=f[i][j];
f[i][j]=max(f[i][j],num[head]+q[head]-i);
}
}
break;
}
case 2:{
for(int re j=1;j<=m;++j){
head=1;tail=0;
for(int re i=1;i<=n;++i){
if(map[i][j]){head=1;tail=0;continue;}
while(i-q[head]>t[kk]&&head<=tail)++head;
while((num[tail]<0||num[tail]-q[tail]+i<f[i][j])&&head<=tail)--tail;
q[++tail]=i;num[tail]=f[i][j];
f[i][j]=max(f[i][j],num[head]-q[head]+i);
}
}
break;
}
case 3:{
for(int re i=1;i<=n;++i){
head=1;tail=0;
for(int re j=m;j>=1;--j){
if(map[i][j]){head=1;tail=0;continue;}
while(q[head]-j>t[kk]&&head<=tail)++head;
while((num[tail]<0||num[tail]+q[tail]-j<f[i][j])&&head<=tail)--tail;
q[++tail]=j;num[tail]=f[i][j];
f[i][j]=max(f[i][j],num[head]+q[head]-j);
}
}
break;
}
case 4:{
for(int re i=1;i<=n;++i){
head=1;tail=0;
for(int re j=1;j<=m;++j){
if(map[i][j]){head=1;tail=0;continue;}
while(j-q[head]>t[kk]&&head<=tail)++head;
while((num[tail]<0||num[tail]-q[tail]+j<f[i][j])&&head<=tail)--tail;
q[++tail]=j;num[tail]=f[i][j];
f[i][j]=max(f[i][j],num[head]-q[head]+j);
}
}
break;
}
}
}
int ans=0;
for(int re i=1;i<=n;++i)for(int re j=1;j<=m;++j)ans=max(ans,f[i][j]);
outint(ans);
return 0;
}