盲人摸象 (bfs+dfs) 2020 jsk蓝桥杯省赛第二次模拟赛
思路:
1:对于正常人,限制条件较少,我们可以直接采用bfs获得最短路径;
2:对于左手盲人或右手盲人,题意为左手或右手有墙才能前进,否则左转,我们可以理解为左手无墙,便向左转,即能转就转,不能转则遍历其他方向。因为盲人行动有墙的限制,所以路线单一,找到一条路则为最短路径。
↑→←↓
对于左手盲人:方向为↑时,遍历方向应为←↑→↓,即顺时针方向遍历。右手盲人同理。我们可以用一个变量储存当前盲人方向。代码如下:
#include <stdio.h>
int n,m,q1,q2,w1,w2,head,tail,a1,b1,c1;
int next[4][2]={0,1,1,0,0,-1,-1,0};
int next1[4][2]={0,-1,-1,0,0,1,1,0};
int next2[4][2]={0,1,-1,0,0,-1,1,0};
int b[44][44];
char a[44][44];
struct dalao
{
int x;
int y;
int s;
}st[1666];
void dfs1(int x,int y,int e,int d)
{
int tx,ty,j;
if(x==q2&&y==w2)
{
a1=e;
return ;
}
for(int i=0;i<4;i++)
{
if(a1) return ;
j=(d-1+i+4)%4;
tx=x+next1[j][0];
ty=y+next1[j][1];
if(tx<0||tx>=n||ty<0||ty>=m||a[tx][ty]=='#')
continue;
dfs1(tx,ty,e+1,j);
}
}
void dfs2(int x,int y,int e,int d)
{
int tx,ty,j;
if(x==q2&&y==w2)
{
b1=e;
return ;
}
for(int i=0;i<4;i++)
{
if(b1) return ;
j=(d-1+i+4)%4;
tx=x+next2[j][0];
ty=y+next2[j][1];
if(tx<0||tx>=n||ty<0||ty>=m||a[tx][ty]=='#')
continue;
dfs2(tx,ty,e+1,j);
}
}
void bfs(int q1,int w1)
{
int tx,ty,ts;
st[head].x=q1;
st[head].y=w1;
st[head].s=1;
tail++;
while(tail>head)
{
for(int i=0;i<4;i++)
{
tx=st[head].x+next[i][0];
ty=st[head].y+next[i][1];
ts=st[head].s+1;
if(tx<0||tx>=n||ty<0||ty>=m||a[tx][ty]=='#'||b[tx][ty])
continue;
b[tx][ty]=1;
st[tail].x=tx;
st[tail].y=ty;
st[tail].s=ts;
tail++;
if(tx==q2&&ty==w2)
{
c1=st[tail-1].s;
return ;
}
}
head++;
}
}
int main()
{
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]=='S')
{
q1=i;
w1=j;
}
if(a[i][j]=='E')
{
q2=i;
w2=j;
}
}
}
dfs1(q1,w1,1,1);
dfs2(q1,w1,1,1);
bfs(q1,w1);
printf("%d\n%d\n%d\n",a1,b1,c1);
return 0;
}