特点: 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; }