题意:一张n*m得网格图,有障碍物,起点是(r,c),每步能向上、下、左、右中的某个方向走一格,向左走不能超过x步,向右走不能超过y步,问从起点可以到达格数?
思路:设一个tag类型的vis[][]标记,tag的结构体里有l、r两个属性,走到 (x,y) 这一格时,vis[x][y].l 表示已经向左走了多少步,vis[x][y].r 表示已经向右走了多少步,如果l r都是-1,表示这格还没访问过。
在满足边界条件、障碍条件的情况下,只有当 (该网格从未被访问过 或 向左走的步数大于此时向左走的步数 或 向右走的步数大于此时向右走的步数) 且 向左向右的步数限制都还在x、y内,才将该点入队访问。
看代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,r,c,x,y;
char s[2005][2005];
int dir[][4]={{0,1},{0,-1},{1,0},{-1,0}};
struct Node{
int x,y;
int l,r;
};
struct tag{
int l,r;
tag(){l=r=-1;}
}vis[2005][2005];
int bfs(){
int ans=0;
queue<Node>q;
Node v;
v.x=r,v.y=c,v.l=0,v.r=0;
q.push(v);
++ans;
vis[r][c].l=0,vis[r][c].r=0;
while(!q.empty()){
auto t=q.front();
q.pop();
for(int i=0;i<4;++i){
Node nt;
//cout<<i<<": ";
nt.x=t.x+dir[i][0], nt.y=t.y+dir[i][1];
nt.l=t.l,nt.r=t.r;
//cout<<dir[i][0]<<" "<<dir[i][1]<<" --- ";
if( s[nt.x][nt.y]=='.' && 0<nt.x && nt.x<=n && 0<nt.y && nt.y<=m ) {
if(i==0) ++nt.r;
if(i==1) ++nt.l;
//nt.l = t.l + dir[i][1]==-1?1:0, nt.r = t.r + dir[i][1]==1?1:0;
//cout<<t.x<<" "<<t.y<<" "<<nt.x<<" "<<nt.y<<" "<<nt.l<<" "<<nt.r<<endl;
if((vis[nt.x][nt.y].l==-1||vis[nt.x][nt.y].l>nt.l||vis[nt.x][nt.y].r>nt.r) && nt.l<=x && nt.r<=y ){
if(vis[nt.x][nt.y].l==-1){
++ans;
//cout<<t.x<<" "<<t.y<<" "<<nt.x<<" "<<nt.y<<" "<<nt.l<<" "<<nt.r<<endl;
}
vis[nt.x][nt.y].l=nt.l;
vis[nt.x][nt.y].r=nt.r;
q.push(nt);
}
}
}
}
return ans;
}
int main(){
scanf("%d%d%d%d%d%d",&n,&m,&r,&c,&x,&y);
for(int i=1;i<=n;++i){
scanf("%s",s[i]+1);
}
printf("%d",bfs());
}