这题不同于其他题的地方就是于虽然也是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;
}