特点:
1:走过的路不能标记,因为等会可能还会走(当需要增加距离爆炸时间的时候)
2: 在没有对顶点做标记的情况下,需要通过将访问过了的4标记为0,以减小搜索范围,
这样才能跳出while(!Q.empty())循环
3: 队列里的时间不是从大到小的,因为4位置会改变时间,比如6,4,2,在遇到4时
会变成6,4,2,6,(见标记2)
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
int m,n,s[10][10],sx,ex,sy,ey;
struct node
{
int x,y,time,step;
};
int dir[4][2]={0,1,0,-1,1,0,-1,0};
void BFS()
{
int i,k,j;
queue<node>Q;
node p,q;
p.x=sx;
p.y=sy;
p.step=6;//表示炸弹剩余时间
p.time=1;//表示已使用时间
Q.push(p);
while(!Q.empty())
{
q=Q.front();
Q.pop();
// if (q.step<=0) 由于队列的时间不是递减的,因此不能置于此处,(遇到了4就会改变其值)
// break;
if (q.x==ex&&q.y==ey)
{
printf ("%d\n",q.time);
return;
}
for (k=0;k<4;++k)
{
p=q;
p.x+=dir[k][0];
p.y+=dir[k][1];
p.step=q.step-1;
if (p.x>=1&&p.y<=m&&p.y>=1&&p.x<=n&&s[p.x][p.y]!=0&&p.step>0)
{
if (s[p.x][p.y]==4)
{
s[p.x][p.y]=0;//到达4,就无需在来一次,因为炸弹剩余时间不会增加
p.step=6;
p.time=q.time+1;
}
if (s[p.x][p.y]==1)
{
p.time=q.time+1;
}
Q.push(p);
}
}
}
printf ("-1\n");
}
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;++i)
for (j=1;j<=m;++j)
{
scanf("%d",&s[i][j]);
if (s[i][j]==2)
sx=i,sy=j;
if (s[i][j]==3)
ex=i,ey=j;
}
BFS();
}
return 0;
}