这题不同于其他题的地方就是于虽然也是bfs,但对于走过的路径不能标记,因为可能还要走,注意题目要求:如果可以,可以走任意多遍。
这就引发了一个问题,如果不缩减搜索范围,怎么可能走得出来呢?应该说这题好就好在不是根据走过的路径来标记,而是根据前后两次踏
上同一位置是bomb离explode的时间长短来标记。简言之,如果第二次踏上一个位置,那么找出路已用的时间肯定是增加了,那为啥还要走上这条
路呢?唯一的追求就是bomb离爆炸的时间增大了。所以可以利用这个条件来标记了。每次在入队前检查下爆炸时间是否比上次在同一位置的大,若
是,则入队;反之,入队无意义了。详见代码一。
从以上的分析中可以引出另一思路,也就是只要进入位置4,那么bomb就会延时到6分钟,最大的延时时间。换句话说,下次再进入该4位置,也
不会获得更大的延时时间了。所以,只要访问过位置4了,就可以直接标记为0位置,表明下次不可在访问。详见代码二。
声明:代码主要思路来源于网络。
代码一:
#include<iostream> #include<queue> using namespace std; int col,row; int map[8][8]; int mark[8][8]; struct node { int x,y,t_use,t_remine; //t_use所走步数,t_remine为bomb离爆炸时间 }start; void store_map() { for(int i=0;i<row;i++) { for(int j=0;j<col;j++) { cin>>map[i][j]; if(map[i][j]==2) { start.x=i; start.y=j; start.t_use=0; start.t_remine=6; } } } } void bfs() { const int help[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; queue<node> myqueue; myqueue.push(start); memset(mark,0,sizeof(mark)); //开始时都是0 mark[start.x][start.y]=6; //起点是6 bool flag=false; int t_remine=0,t_use=0; while(!myqueue.empty() && !flag) { node tmp=myqueue.front(); myqueue.pop(); for(int i=0;i<4;i++) { node temp; temp.x=tmp.x+help[i][0]; temp.y=tmp.y+help[i][1]; if(map[temp.x][temp.y]!=0 && temp.x>=0 && temp.x<row && temp.y>=0 && temp.y<col) //没越界并不是0,才可访问 { temp.t_use=tmp.t_use+1; temp.t_remine=tmp.t_remine-1; if(map[temp.x][temp.y]==4) { temp.t_remine=6; } else if(map[temp.x][temp.y]==3) { t_remine=tmp.t_remine-1; t_use=tmp.t_use+1; flag=true; } if(temp.t_remine>1 && mark[temp.x][temp.y]<temp.t_remine) //满足条件才入队 { mark[temp.x][temp.y]=temp.t_remine; myqueue.push(temp); } } if(flag) break; } } if(flag) { if(t_remine>0) cout<<t_use; else cout<<-1; } else cout<<-1; cout<<endl; } int main() { int t_case; cin>>t_case; while(t_case--) { cin>>row>>col; store_map(); bfs(); } return 0; }
代码二:
#include<iostream> #include<queue> using namespace std; int map[8][8]; int row,col; struct node { int x,y,step,time; //step为走的步数,time为bomb离爆炸时间 }start; void store_map() { for(int i=0;i<row;i++) { for(int j=0;j<col;j++) { cin>>map[i][j]; if(map[i][j]==2) { start.x=i; start.y=j; start.step=0; start.time=6; } } } } void bfs() { const int help[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; queue<node> q; q.push(start); node p1,p2; int i; while(!q.empty()) { p1=q.front(); q.pop(); for(i=0;i<4;i++) { p2.step=p1.step+1; p2.time=p1.time-1; p2.x=p1.x+help[i][0]; p2.y=p1.y+help[i][1]; if(p2.x>=0 && p2.x<row && p2.y>=0 && p2.y<col && map[p2.x][p2.y]!=0 && p2.time>0) //注意这里的p2.time>0 { if(map[p2.x][p2.y]==3) { cout<<p2.step<<endl; return; } else if(map[p2.x][p2.y]==4) { p2.time=6; map[p2.x][p2.y]=0; //该位置4不能再访问了 } q.push(p2); } } } cout<<-1<<endl; } int main() { int t_case; cin>>t_case; while(t_case--) { cin>>row>>col; store_map(); bfs(); } return 0; }