P2254 [NOI2005] 瑰丽华尔兹
首先我们可以得到一个很简单的暴力动规
设\(f(i,j,k)\)表示当前在\((i,j)\),经过的时间为k时的最长移动距离。
于是我们可以很朴素的转移。
时间复杂度是\(O(nmt)\)的
由于\(t\)太大了,不能直接枚举\(t\),但是\(k\)很小,可以作为\(dp\)的一维。
对于一个点\((i,j)\),我们对于一个操作\(k\),我们只能够\(O(1)\)转移。
如果是暴力,必然是\(O(n)\)的:
\(f[i][j][k]=max(f[i][j][k],f[i][j-l][k])\)
但是我们可以发现这个用来转移的区间\(j\)~\(j-l\)是单调递增的。
用单调队列优化即可。
但是注意一下这里移动距离和当前位置是有关系的,用单调队列的时候容易写错,注意一下。
这里可以用dxdy来转移,也可以用四大段,均可。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<deque>
#include<iomanip>
using namespace std;
inline int r()
{
int s=0,k=1;char c=getchar();
while(!isdigit(c))
{
if(c=='-')k=-1;
c=getchar();
}
while(isdigit(c))
{
s=s*10+c-'0';
c=getchar();
}
return s*k;
}
int n,m,t,tx,ty,f[2005][2005],from[100001],to[100001],ti[100001];//上下左右
char c[2001][2010],s[2001];
deque<int>q;
deque<int>bh;
int main()
{
int ans=0;
n=r();m=r();tx=r();ty=r();t=r();
for(int i=1;i<=n;i++)
{
cin>>(s+1);
for(int j=1;j<=m;j++)
c[i][j]=s[j];
}
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
f[i][j]=-1e9;
f[tx][ty]=0;
for(int i=1;i<=t;i++)
{
from[i]=r();
to[i]=r();
ti[i]=r();
}
for(int k=1;k<=t;k++)
{
int now=to[k]-from[k]+1;
if(ti[k]==1)//上
{
for(int j=1;j<=m;j++)
{
q.clear();bh.clear();
for(int i=n;i;i--)
{
if(c[i][j]=='x')
{
q.clear();
bh.clear();f[i][j]=-1e9;
continue;
}
while(!q.empty()&&bh.front()-i>now)q.pop_front(),bh.pop_front();
while(!q.empty()&&q.back()+abs(bh.back()-i)<=f[i][j])q.pop_back(),bh.pop_back();
q.push_back(f[i][j]);
bh.push_back(i);
int w=q.front();
f[i][j]=w+abs(bh.front()-i);
}
}
}
if(ti[k]==2)//下
{
for(int j=1;j<=m;j++)
{
q.clear();bh.clear();
for(int i=1;i<=n;i++)
{
if(c[i][j]=='x')
{
q.clear();
bh.clear();f[i][j]=-1e9;
continue;
}
while(!q.empty()&&i-bh.front()>now)q.pop_front(),bh.pop_front();
while(!q.empty()&&q.back()+abs(bh.back()-i)<=f[i][j])q.pop_back(),bh.pop_back();
q.push_back(f[i][j]);
bh.push_back(i);
int w=q.front();
f[i][j]=w+abs(bh.front()-i);
}
}
}
if(ti[k]==3)//左
{
for(int i=1;i<=n;i++)
{
q.clear();bh.clear();
for(int j=m;j;j--)
{
if(c[i][j]=='x')
{
q.clear();
bh.clear();f[i][j]=-1e9;
continue;
}
while(!q.empty()&&bh.front()-j>now)q.pop_front(),bh.pop_front();
while(!q.empty()&&q.back()+abs(bh.back()-j)<=f[i][j])q.pop_back(),bh.pop_back();
q.push_back(f[i][j]);
bh.push_back(j);
int w=q.front();
f[i][j]=w+abs(bh.front()-j);
}
}
}
if(ti[k]==4)//右
{
for(int i=1;i<=n;i++)
{
q.clear();bh.clear();
for(int j=1;j<=m;j++)
{
if(c[i][j]=='x')
{
q.clear();
bh.clear();f[i][j]=-1e9;
continue;
}
while(!q.empty()&&j-bh.front()>now)q.pop_front(),bh.pop_front();
while(!q.empty()&&q.back()+abs(bh.back()-j)<=f[i][j])q.pop_back(),bh.pop_back();
q.push_back(f[i][j]);
bh.push_back(j);
int w=q.front();
f[i][j]=w+abs(bh.front()-j);
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,f[i][j]);
}
cout<<ans;
}
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15055570.html