锻炼身体
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);
}