LYZ搬来国赛题......又是2005的!
感觉NOI2005的题都好神啊。
DP。
设f[i][j]为走到(i,j)的最大值。时间那一维滚动掉。
对于每一个时间段,枚举开始位置,进行DP。
从每个开始位置向输入的方向进行DP,用单调队列优化一下。
遇到障碍物就要清空队列。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int n,m,sx,sy,k,ans; 7 int ob[205][205]; 8 int dx[]={0,-1,1,0,0}; 9 int dy[]={0,0,0,-1,1}; 10 int f[205][205]; 11 struct data{int pos,val;}q[205]; 12 int hd,tl; 13 14 void cal(int x,int y,int len,int dir) 15 { 16 hd=1,tl=0; 17 for(int i=1;x>0&&x<=n&&y>0&&y<=m;i++,x+=dx[dir],y+=dy[dir]) 18 { 19 if(ob[x][y]){hd=1,tl=0;continue;} 20 while(hd<=tl&&q[tl].val+i-q[tl].pos<f[x][y])tl--; 21 q[++tl]=(data){i,f[x][y]}; 22 if(q[tl].pos-q[hd].pos>len)hd++; 23 f[x][y]=q[hd].val+i-q[hd].pos; 24 ans=max(ans,f[x][y]); 25 } 26 } 27 28 int main() 29 { 30 scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&k); 31 for(int i=1;i<=n;i++) 32 { 33 char tmp[205]; 34 scanf("%s",tmp+1); 35 for(int j=1;j<=m;j++) 36 if(tmp[j]=='x')ob[i][j]=1; 37 } 38 memset(f,0xf3,sizeof(f)); 39 f[sx][sy]=0; 40 for(int i=1;i<=k;i++) 41 { 42 int st,ed,dir; 43 scanf("%d%d%d",&st,&ed,&dir); 44 int len=ed-st+1; 45 if(dir==1)for(int j=1;j<=m;j++)cal(n,j,len,dir); 46 if(dir==2)for(int j=1;j<=m;j++)cal(1,j,len,dir); 47 if(dir==3)for(int j=1;j<=n;j++)cal(j,m,len,dir); 48 if(dir==4)for(int j=1;j<=n;j++)cal(j,1,len,dir); 49 } 50 printf("%d",ans); 51 return 0; 52 }