• #单调队列#JZOJ 1753 锻炼身体


    题目

    一个(n*m)的矩阵,有些格子不能经过,有(k)个时段,
    要么停留某个格子,要么沿时段规定的方向移动,问最多能够移动多少次
    (n,m,kleq 200)


    分析

    题目已经提示了(O(nmk)),考虑朴素的搜索为(O(n^2mk))的,
    考虑用单调队列优化此过程使复杂度降至1s内


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=201; struct rec{int l,r,opt;}ques[N];
    int n,m,zx,zy,Q,q[N],dp[N][N],f[N][N],a[N][N],ans;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed max(int a,int b){return a>b?a:b;}
    bool cmp(rec x,rec y){return x.l<y.l;}
    signed main(){
    	n=iut(),m=iut(),zx=iut(),zy=iut(),Q=iut();
    	memset(dp,0xcf,sizeof(dp)),dp[zx][zy]=0;
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=1;j<=m;++j){
    		rr char c=getchar();
    		while (c!='.'&&c!='x') c=getchar();
    		a[i][j]=c=='.';
    	}
    	for (rr int i=1;i<=Q;++i)
    	    ques[i]=(rec){iut(),iut(),iut()};
    	sort(ques+1,ques+1+Q,cmp);
    	for (rr int T=1;T<=Q;++T){
    		rr int len=ques[T].r-ques[T].l+1,head,tail;
    		memcpy(f,dp,sizeof(dp));
    		switch (ques[T].opt){
    			case 1:{
    				for (rr int j=1;j<=m;++j){
    				    head=1,tail=0;
    					for (rr int i=n;i>=1;--i){
    						if (!a[i][j]){
    							head=1,tail=0;
    						    continue;
    						}
    						while (head<=tail&&i+len<q[head]) ++head;
    						while (head<=tail&&f[q[tail]][j]+q[tail]<=f[i][j]+i) --tail;
    						if (f[i][j]>=0) q[++tail]=i;
    						if (head<=tail) dp[i][j]=max(dp[i][j],f[q[head]][j]+q[head]-i);
    					}
    				}
    				break;
    			}
    			case 2:{
    				for (rr int j=1;j<=m;++j){
    				    head=1,tail=0;
    					for (rr int i=1;i<=n;++i){
    						if (!a[i][j]){
    							head=1,tail=0;
    						    continue;
    						}
    						while (head<=tail&&q[head]+len<i) ++head;
    						while (head<=tail&&f[q[tail]][j]-q[tail]<=f[i][j]-i) --tail;
    						if (f[i][j]>=0) q[++tail]=i;
    						if (head<=tail) dp[i][j]=max(dp[i][j],f[q[head]][j]+i-q[head]);
    					}
    				}
    				break;
    			}
    			case 3:{
    				for (rr int i=1;i<=n;++i){
    				    head=1,tail=0;
    					for (rr int j=m;j>=1;--j){
    						if (!a[i][j]){
    							head=1,tail=0;
    						    continue;
    						}
    						while (head<=tail&&j+len<q[head]) ++head;
    						while (head<=tail&&f[i][q[tail]]+q[tail]<=f[i][j]+j) --tail;
    						if (f[i][j]>=0) q[++tail]=j;
    						if (head<=tail) dp[i][j]=max(dp[i][j],f[i][q[head]]+q[head]-j);
    					}
    				}
    				break;
    			}
    			case 4:{
    				for (rr int i=1;i<=n;++i){
    				    head=1,tail=0;
    					for (rr int j=1;j<=m;++j){
    						if (!a[i][j]){
    							head=1,tail=0;
    						    continue;
    						}
    						while (head<=tail&&q[head]+len<j) ++head;
    						while (head<=tail&&f[i][q[tail]]-q[tail]<=f[i][j]-j) --tail;
    						if (f[i][j]>=0) q[++tail]=j;
    						if (head<=tail) dp[i][j]=max(dp[i][j],f[i][q[head]]+j-q[head]);						
    					}
    				}
    				break;
    			}
    		}
    	}
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=1;j<=m;++j)
    	    ans=max(ans,dp[i][j]);
    	return !printf("%d",ans);
    }
    
  • 相关阅读:
    成功在C#和VB中将shp转换为CAD
    java 提取字符串中的数字
    java 通用文件下载 excel,pdf,word,jpg,exe,rar
    java org 写excel
    java 通用文件下载 excel,pdf,word,jpg
    重建MDB空间网格大小的工具
    redis5.0 Cluster集群搭建
    选中对象【WPF】自定义控件之依赖属性
    成员函数对象类的const和非const成员函数的重载
    设备注册Linux加载DTS设备节点的过程(以高通8974平台为例)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13820525.html
Copyright © 2020-2023  润新知