zoukankan      html  css  js  c++  java
  • 【[NOI2005]瑰丽华尔兹】

    非常无脑和码农的单调队列优化(dp)

    我们发现一个时间段内移动的情况是一样的,而时间段的数目又非常少,所以可以直接按照时间段来进行(dp)

    由于每一次(dp)的移动距离都是小于等于某一个固定值的,于是可以直接上单调队列优化

    复杂度(O(nmk))

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 205
    #define max(a,b) ((a)>(b)?(a):(b))
    int dp[maxn][maxn],now[maxn][maxn];
    int n,m,sx,sy,K;
    int S,E,wind;
    char map[maxn][maxn];
    int h,t,q[maxn];
    inline int read()
    {
    	char c=getchar();
    	int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    		x=(x<<3)+(x<<1)+c-48,c=getchar();
    	return x;
    }
    int main()
    {
    	n=read(),m=read(),sx=read(),sy=read(),K=read();
    	for(re int i=1;i<=n;i++) scanf("%s",map[i]+1);
    	memset(dp,-20,sizeof(dp)),memset(now,-20,sizeof(now));
    	now[sx][sy]=dp[sx][sy]=0;
    	for(re int O=1;O<=K;O++)
    	{
    		S=read(),E=read(),wind=read();
    		int T=E-S+1;
    		memset(now,-20,sizeof(now));
    		if(wind==4)
    		{
    			for(re int i=1;i<=n;i++)
    			{
    				h=1,t=0;
    				memset(q,0,sizeof(q));
    				for(re int j=2;j<=m;j++)
    				{
    					while(h<=t&&dp[i][q[t]]-q[t]<dp[i][j-1]-j+1) t--;
    					q[++t]=j-1;
    					if(map[i][j-1]=='x') while(h<=t) h++;
    					if(map[i][j]=='x') continue;
    					while(h<=t&&q[h]+T<j) h++;
    					if(h<=t) now[i][j]=max(dp[i][j],j+dp[i][q[h]]-q[h]);
    				}
    			}
    		}
    		if(wind==3)
    		{
    			for(re int i=1;i<=n;i++)
    			{
    				h=1,t=0;
    				memset(q,0,sizeof(q));
    				for(re int j=m-1;j>=1;j--)
    				{
    					while(h<=t&&dp[i][q[t]]+q[t]<dp[i][j+1]+j+1) t--;
    					q[++t]=j+1;
    					if(map[i][j+1]=='x') while(h<=t) h++;
    					if(map[i][j]=='x') continue;
    					while(h<=t&&j+T<q[h]) h++;
    					if(h<=t) now[i][j]=max(dp[i][j],dp[i][q[h]]+q[h]-j);
    				}
    			}
    		}
    		if(wind==2)
    		{
    			for(re int j=1;j<=m;j++)
    			{
    				h=1,t=0;
    				memset(q,0,sizeof(q));
    				for(re int i=2;i<=n;i++)
    				{
    					while(h<=t&&dp[q[t]][j]-q[t]<dp[i-1][j]-i+1) t--;
    					q[++t]=i-1;
    					if(map[i-1][j]=='x') while(h<=t) h++;
    					if(map[i][j]=='x') continue;
    					while(h<=t&&q[h]+T<i) h++;
    					if(h<=t) now[i][j]=max(dp[i][j],i+dp[q[h]][j]-q[h]);
    				}
    			}
    		}
    		if(wind==1)
    		{
    			for(re int j=1;j<=m;j++)
    			{
    				h=1,t=0;
    				for(re int i=n-1;i>=1;i--)
    				{
    					while(h<=t&&dp[q[t]][j]+q[t]<dp[i+1][j]+i+1) t--;
    					q[++t]=i+1;
    					if(map[i+1][j]=='x') while(h<=t) h++;
    					if(map[i][j]=='x') continue;
    					while(h<=t&&i+T<q[h]) h++;
    					if(h<=t) now[i][j]=max(dp[i][j],dp[q[h]][j]+q[h]-i);
    				}
    			}
    		}
    		for(re int i=1;i<=n;i++)
    			for(re int j=1;j<=m;j++)
    				dp[i][j]=max(dp[i][j],now[i][j]);
    	}
    	int ans=0;
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=m;j++)
    			ans=max(ans,dp[i][j]);
    	std::cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    student
    super
    java 浮点数
    视图
    日期转换函数
    左外连接,右外连接,全外连接,自然连接,自连接区别
    Python中sys.argv[ ]的用法
    0 Scala
    统计字符串字符个数
    3个链表排序整合到一起
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205725.html
Copyright © 2011-2022 走看看