CF877D 题解
思路讲解
本题是一道模板迷宫最短路线题的加强版,所以思路也就自然很明显了,本题应该使用广度优先搜索 BFS。
因为本题一次可以走 # 的格子放到队列里就行了。其他的和模板 BFS 没什么区别了。
不过有一些容易使代码不 AC 的点:
-
如果往一个方向遍历从
1 步到k 步究竟走多少步合法时,如果遇到一个出格,那么直接break,因为再往后遍历也一定出格;同理,只要有一个是#,那么直接停止遍历,因为就算一次走多个格也是不能穿墙的。 -
本题疑问一次可以走
k 步 以内,所以需要放进队列的比较多,所以可以在加入新结点时就判断一下是不是到达了终点,如果到了就直接输出,这样可以防止再多循环遍历一次而造成的 TLE。
说了这么多,上代码:
AC CODE:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int maxn=1000+5;
char a[maxn][maxn],vis[maxn][maxn];
int pos[4][2]={-1,0,0,-1,1,0,0,1};//增加新节点
int p1,m1,p2,m2;
struct Node
{
int x,y;
int step;
};//存结点
queue<Node> q;
void bfs()
{
Node now,nt;
now.x=p1;now.y=m1;now.step=0;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
if(now.x==p2&&now.y==m2)//到终点
{
cout<<now.step;
return;
}
for(int i=0;i<4;i++)
{
for(int j=1;j<=k;j++)
{
int nx=now.x+pos[i][0]*j;
int ny=now.y+pos[i][1]*j;//新增结点
if(nx<1||ny<1||nx>n||ny>m)break;//出格
if(a[nx][ny]=='#')break;//是墙
if(vis[nx][ny]==0)
{
if(nx==p2&&ny==m2)//到终点
{
cout<<now.step+1;
return;
}
vis[nx][ny]=1;
nt.x=nx;
nt.y=ny;
nt.step=now.step+1;
q.push(nt);//加到队列里
}
}
}
}
cout<<-1;//没有可行路线
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) cin>>a[i][j];
}
cin>>p1>>m1>>p2>>m2;
memset(vis,0,sizeof(vis));
bfs();
return 0;
}