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;
}
posted @ 2021-07-24 16:40  lei_yu  阅读(36)  评论(0编辑  收藏  举报