锻炼身体

锻炼身体

Description

胖子很有钱。他购买了一个先进的跑步机(真的不一样哦~~~~)。
  这个跑步机是这样的:
  1. 可以把它看成一个N*M的矩阵。有的格子是障碍不能经过(用x表示),有的格子是空地可以经过(用.表示)。
  2. 对于每一个时段,跑步机有不同的倾斜方向。由于胖子太胖了,所以他这个时候只有2种选择:要么沿这个方向移动(每秒移动1个格子),或者艰难的保持在原来的位置不动。
  现在胖子已经设定好了跑步机在不同时段中的倾斜方向。众所周知,保持在原地不动是不会做功的。胖子要减肥就要做功。所以他想知道他最多能够跑多长的路程。

Input

第一行5个正整数N,M,X,Y,K。 X,Y是胖子的初始位置,数据保证这个点不是障碍。
  接下来N行,每行M个字符,表示跑步机上的地形。
  最后K行,每行3个正整数S,T,W。S表示这个时段的开始时间,T(T<=10000)表示这个时段的结束时间。W表示该时段的倾斜方向。(1:上 2:下 3:左 4:右)

Output

一个整数LEN,表示胖子最多可以跑动的距离。

Sample Input

4 5 4 1 3
…xx.

…x.

1 3 4
4 5 1
6 7 2

Sample Output

6

数据范围

对于60%的数据 N,M<=80 K<=50
  对于100%的数据 N,M<=200,K<=200

题解

显然是DP
比较容易想到O(Tnmk)的DP(其实O(Tnmk)也能过)
但时间复杂度太高,考虑优化
发现更新的时候具有单调性,可以用单调队列优化
设f[i][j][k]为第i段时间,j,k这个位置的最大路程
以向上为例 不等式为f[j][k]+j<f[t][k]+t,那么t比j优

code

O(Tmnk)的DP

#include<cstdio>
#include<cctype>
#include<cstring>
#define max(a,b) (a>b?a:b)
#define R register
#define N 255
using namespace std;
int n,m,x,y,q,f[N][N],map[N][N],g[N][N],ans;
int fx[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
inline void rd(int &x){
	x=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
}
int main(){
	rd(n),rd(m),rd(x),rd(y),rd(q);
	for(R int i=1;i<=n;++i){
		char ch=getchar();
		while(ch!='.'&&ch!='x')ch=getchar();
		for(R int j=1;j<=m;++j,ch=getchar())
			g[i][j]=f[i][j]=-1,map[i][j]=(ch=='x');
	}
	g[x][y]=f[x][y]=0;
	for(R int i=1;i<=q;++i){
		int s,t,w,xx,yy;
		rd(s),rd(t),rd(w),--w;
		for(R int j=1;j<=n;++j){
			for(R int k=1;k<=m;++k)
			if(!map[j][k]&&f[j][k]>=0){
				for(R int l=1;l<=t-s+1;++l){
					xx=j+l*fx[w][0],yy=k+l*fx[w][1];
					if(xx<0||xx>n||yy<0||yy>m||map[xx][yy])break;
					g[xx][yy]=max(g[xx][yy],f[j][k]+l);
				}
			}
		}
		for(R int j=1;j<=n;++j)
			for(R int k=1;k<=m;++k)
				f[j][k]=g[j][k],ans=max(ans,f[j][k]);
		printf("%d %d\n",i,ans); 
	}
	for(R int i=1;i<=n;++i)
		for(R int j=1;j<=m;++j)
			ans=max(ans,f[i][j]);
	printf("%d",ans);
}

单调队列优化

#include<cstdio>
#include<cctype>
#include<cstdlib>
#define max(a,b) (a>b?a:b) 
#define R register int
#define N 255
using namespace std;
int f[N][N],g[N][N],map[N][N],d[N],ans;
inline void rd(int &x){
	x=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
}
int main(){
	R n,m,x,y,q;
	rd(n),rd(m),rd(x),rd(y),rd(q);
	for(R i=1;i<=n;++i){
		char ch=getchar();
		while(ch!='.'&&ch!='x')ch=getchar();
		for(R j=1;j<=m;++j,ch=getchar())
			g[i][j]=f[i][j]=-1,map[i][j]=(ch=='x');
	}
	f[x][y]=0;
	for(R i=1;i<=q;++i){
		R s,time,w,sum,h,t;
		rd(s),rd(time),rd(w),sum=time-s+1;
		if(w==1){
			for(R k=1;k<=m;++k){
				t=0,d[h=1]=0;
				for(R j=n;j;--j){
					if(map[j][k]){h=t+1;continue;}
					while(d[h]-j>sum&&h<=t)++h;
 					while(h<t&&f[d[h]][k]+d[h]<f[d[h+1]][k]+d[h+1])++h;
					if(h<=t)g[j][k]=max(g[j][k],f[d[h]][k]+d[h]-j);
					if(f[j][k]!=-1){
						while(h<=t&&f[j][k]>f[d[t]][k]+d[t]-j)--t;
						d[++t]=j;
					}	
				}
			}	
		}
		if(w==2){
		for(R k=1;k<=m;++k){
				t=0,d[h=1]=0;
				for(R j=1;j<=n;++j){
					if(map[j][k]){h=t+1;continue;}
					while(j-d[h]>sum&&h<=t)++h;
 					while(h<t&&f[d[h]][k]-d[h]<f[d[h+1]][k]-d[h+1])++h;
					if(h<=t)g[j][k]=max(g[j][k],f[d[h]][k]+j-d[h]);
					if(f[j][k]!=-1){
						while(h<=t&&f[j][k]>f[d[t]][k]+j-d[t])--t;
						d[++t]=j;	
					}
				}
			}
		}
		if(w==3){
			for(R j=1;j<=n;++j){
				t=0,d[h=1]=0;
				for(R k=m;k;--k){
					if(map[j][k]){h=t+1;continue;}
					while(d[h]-k>sum&&h<=t)++h;
					while(h<t&&f[j][d[h]]+d[h]<f[j][d[h+1]]+d[h+1])++h;
					if(h<=t)g[j][k]=max(g[j][k],f[j][d[h]]+d[h]-k);
					if(f[j][k]!=-1){
						while(h<=t&&f[j][k]>f[j][d[t]]+d[t]-k)--t;
						d[++t]=k;
					}
				}
			}
		}
		if(w==4){
			for(R j=1;j<=n;++j){
				t=0,d[h=1]=0;
				for(R k=1;k<=m;++k){
					if(map[j][k]){h=t+1;continue;}
					while(k-d[h]>sum&&h<=t)++h;
					while(h<t&&f[j][d[h]]-d[h]<f[j][d[h+1]]-d[h+1])++h;
					if(h<=t)g[j][k]=max(g[j][k],f[j][d[h]]+k-d[h]);
					if(f[j][k]!=-1){	
						while(h<=t&&f[j][k]>f[j][d[t]]+k-d[t])--t;
						d[++t]=k;
					}
				}
			}
		}
		for(R j=1;j<=n;++j)
			for(R k=1;k<=m;++k)
			f[j][k]=g[j][k];
	}
	for(R i=1;i<=n;++i)
		for(R j=1;j<=m;++j)
			ans=max(ans,f[i][j]);
	printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值