这题是一道简单的BFS,原本没有AC是以为不能走重复的路。后来发现这不是一道普通的BFS,也就是说,我可以往回走(走已经走过的结点),找到更优的解决方案.所以我们要设置一个记录障碍信息的数组(且称为bar),这个数组记录了当前节点已经走过的障碍数.(0,1,2,...,k)。
1.如果已经连续穿越了K的障碍,下一个他只能走到不是障碍(maze[x][y]==0)的地方。
2.如果BFS过程中,发现当前节点走到已经走过的节点的所需要穿越的障碍数量更少,覆盖掉已经走过的哪一个结点。
其余部分和普通BFS没有区别。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int dis[25][25]; //记录距离
int maze[25][25]; //迷宫情况
int bar[25][25]; //记录点 x,y 的已走过的障碍数量
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int n,m,k;
queue <pair<int,int> > q; //队列,记录x,y;
pair<int,int> p;
bool BFS(int x,int y)
{
for (int i=0;i<4;i++)
{
// 对x,y 四周探测,对符合条件的节点进行更新 (注意后两个条件)
if (x+dx[i]>=1&&x+dx[i]<=m&&y+dy[i]>=1&&y+dy[i]<=n&&(bar[x][y]+1<bar[x+dx[i]][y+dy[i]]||dis[x+dx[i]][y+dy[i]]==-1))
{
if (maze[x+dx[i]][y+dy[i]]==1&&bar[x][y]<k)
{
bar[x+dx[i]][y+dy[i]]=bar[x][y]+1;
dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
p.first=x+dx[i];
p.second=y+dy[i];
q.push(p);
}
else if (maze[x+dx[i]][y+dy[i]]==0)
{
bar[x+dx[i]][y+dy[i]]=0;
dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
p.first=x+dx[i];
p.second=y+dy[i];
q.push(p);
}
if (x+dx[i]==m&&y+dy[i]==n)
return true;//找到终点后,返回真,BFS可以结束
}
}
return false;
}
int main()
{
int t,x,y;
scanf ("%d",&t);
while(t--)
{
scanf ("%d %d",&m,&n);
scanf ("%d",&k);
memset(dis,-1,sizeof(dis));
memset(bar,-1,sizeof(bar));
memset(maze,-1,sizeof(maze));
for (int i=1;i<=m;i++)
{
for (int j=1;j<=n;j++)
{
scanf ("%d",&maze[i][j]);
}
}
p.first=1;
p.second=1;
dis[1][1]=0;
bar[1][1]=0;
q.push(p);
while(!q.empty())
{
x=q.front().first;
y=q.front().second;
if (BFS(x,y))
break;
q.pop();
}
while(!q.empty())
q.pop();
printf ("%d\n",dis[m][n]);
}
return 0;
}