NOI2005瑰丽华尔兹

Description

link

不知怎么简述题意了……看题吧……

Solution

一道不错的题目吧

定义 (f[i][x][y]) 为在 (i) 时在 ((x,y)) 上的最大经过长度

由背包的一些思想,我们可以滚掉第一维

在每个可以移动的区间的时候我们对该行或列进行更新

更新的时候的限制在障碍点和时间的限制

更新的方式是(f[x][y]=f[x][y-len]+len)

啊就是意会一下吧……

这里我们发现可以上单调队列处理这个东西

然后就对于每个区间做一下就好了

Code

#include<bits/stdc++.h>
using namespace std;
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
		return res*f;
	}
	const int N=210;
	int f[N][N],n,m,k,ans;
	char mp[N][N];
	int fx[5]={0,-1,1,0,0};
	int fy[5]={0,0,0,-1,1};
	struct node{
		int val,pos;
	};deque<node> q;
	inline bool in(int x,int y){return x<=n&&x>=1&&y>=1&&y<=m;}
	inline void dp(int x,int y,int d,int tim)
	{
		q.clear();
		for(int i=1;in(x,y);++i,x+=fx[d],y+=fy[d])
		{
			if(mp[x][y]=='x') {q.clear(); continue;} 
			while(q.size()&&q.back().val+i-q.back().pos<f[x][y]) q.pop_back();
			q.push_back((node){f[x][y],i}); 
			while(q.size()&&q.back().pos-q.front().pos>tim) q.pop_front();
			f[x][y]=q.front().val+i-q.front().pos;
			ans=max(ans,f[x][y]);
		}return ;
	}
	signed main()
	{
		n=read(); m=read();
		int p=read(),q=read(); k=read();
		memset(f,-0x3f,sizeof(f)); f[p][q]=0;
		for(int i=1;i<=n;++i) scanf("%s",mp[i]+1);
		while(k--)
		{
			int s=read(),t=read(),d=read();
			if(d==1) for(int i=1;i<=m;++i) dp(n,i,d,t-s+1);
			if(d==2) for(int i=1;i<=m;++i) dp(1,i,d,t-s+1);
			if(d==3) for(int i=1;i<=n;++i) dp(i,m,d,t-s+1);
			if(d==4) for(int i=1;i<=n;++i) dp(i,1,d,t-s+1); 
		}printf("%d
",ans);
		return 0;
	}
}
signed main(){return yspm::main();}

Review

没啥 (review) 的……

在每次更新的时候记得清空 (deque) 吧……

原文地址:https://www.cnblogs.com/yspm/p/12769361.html