传送门
解题思路
对每一段时间进行操作,dp[i][j][k]表示在第k次操作结束时在位置(i,j)上的最大收益。
首先k这一维可以滚动数组优化掉。
然后对每个方向进行分类讨论,再对每一行/列加上一个单调队列优化即可。
注意碰到障碍就把队列清空,单调队列里的权值是dp值加(或者减)行数(或者列数)。根据不同方向分类讨论即可。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,x,y,t,now,dp[205][205][2],ma[205][205],ans,tp,l,r;
void work4(int t){
for(int i=1;i<=n;i++){
deque<int> q;
for(int j=1;j<=m;j++){
if(ma[i][j]){
while(!q.empty()) q.pop_back();
continue;
}
dp[i][j][now^1]=dp[i][j][now];
while(!q.empty()&&dp[i][j][now]-j>dp[i][q.back()][now]-q.back()) q.pop_back();
q.push_back(j);
while(!q.empty()&&j-q.front()>t) q.pop_front();
if(!q.empty()) dp[i][j][now^1]=max(dp[i][j][now^1],dp[i][q.front()][now]+j-q.front());
ans=max(ans,dp[i][j][now^1]);
}
}
}
void work3(int t){
for(int i=1;i<=n;i++){
deque<int> q;
for(int j=m;j>=1;j--){
if(ma[i][j]){
while(!q.empty()) q.pop_back();
continue;
}
dp[i][j][now^1]=dp[i][j][now];
while(!q.empty()&&dp[i][j][now]+j>dp[i][q.back()][now]+q.back()) q.pop_back();
q.push_back(j);
while(!q.empty()&&q.front()-j>t) q.pop_front();
if(!q.empty()) dp[i][j][now^1]=max(dp[i][j][now^1],dp[i][q.front()][now]+q.front()-j);
ans=max(ans,dp[i][j][now^1]);
}
}
}
void work2(int t){
for(int j=1;j<=m;j++){
deque<int> q;
for(int i=1;i<=n;i++){
if(ma[i][j]){
while(!q.empty()) q.pop_back();
continue;
}
dp[i][j][now^1]=dp[i][j][now];
while(!q.empty()&&dp[i][j][now]-i>dp[q.back()][j][now]-q.back()) q.pop_back();
q.push_back(i);
while(!q.empty()&&i-q.front()>t) q.pop_front();
if(!q.empty()) dp[i][j][now^1]=max(dp[i][j][now^1],dp[q.front()][j][now]+i-q.front());
ans=max(ans,dp[i][j][now^1]);
}
}
}
void work1(int t){
for(int j=1;j<=m;j++){
deque<int> q;
for(int i=n;i>=1;i--){
if(ma[i][j]){
while(!q.empty()) q.pop_back();
continue;
}
dp[i][j][now^1]=dp[i][j][now];
while(!q.empty()&&dp[i][j][now]+i>dp[q.back()][j][now]+q.back()) q.pop_back();
q.push_back(i);
while(!q.empty()&&q.front()-i>t) q.pop_front();
if(!q.empty()) dp[i][j][now^1]=max(dp[i][j][now^1],dp[q.front()][j][now]+q.front()-i);
ans=max(ans,dp[i][j][now^1]);
}
}
}
int main(){
ios::sync_with_stdio(false);
memset(dp,-0x3f,sizeof(dp));
cin>>n>>m>>x>>y>>k;
dp[x][y][0]=dp[x][y][1]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
if(c=='x') ma[i][j]=1;
}
}
for(int i=1;i<=k;i++){
cin>>l>>r>>tp;
t=r-l+1;
if(tp==1) work1(t);
if(tp==2) work2(t);
if(tp==3) work3(t);
if(tp==4) work4(t);
now^=1;
}
cout<<ans;
return 0;
}
//NOI2005 Day1t1