题目:
题目大意:
题目让我们求两点间的最短路径长度,显然是需要广搜,因为广搜先搜到一定就是最短路,深搜可以搜索路径,但搜到的不一定最短,往往都需要多次回溯和判断,耗时太长,只能过1个点。
做题思路:
刚开始做这题时,我毫不犹豫的打完了深搜的代码(虽然我知道是广搜),然后一直TLE,我还全然没发现自己写错了算法,我的深搜错误代码:
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("abm,avx,mmx,popcnt,sse,sse2,sse3,ssse3,sse4")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<cmath>
#define re
using namespace std;
int qread() {
int x(0),y(1);char c=getchar();
while(c<'0'||c>'9') {
if(c=='-')y=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*y;
}
bool b[1001][1001];
int f[1001][1001];
int s,N;
void dfs(int x,int y,int tx,int ty,int step) {
if(x==tx&&y==ty) {
s=min(step,s);
return;
}
if(step>=s) return;
b[x][y]=1;
if(x+1<=N&&f[x+1][y]==0&&b[x+1][y]==0)
dfs(x+1,y,tx,ty,step+1);
if(y+1<=N&&f[x][y+1]==0&&b[x][y+1]==0)
dfs(x,y+1,tx,ty,step+1);
if(x-1>=1&&f[x-1][y]==0&&b[x-1][y]==0)
dfs(x-1,y,tx,ty,step+1);
if(y-1>=1&&f[x][y-1]==0&&b[x][y-1]==0)
dfs(x,y-1,tx,ty,step+1);
b[x][y]=0;
}
int main() {
int i,j;
N=qread();
char c;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
c = getchar();
while (c != '0' && c != '1') c = getchar();
f[i][j] = c - '0';
}
}
int sx(qread()),sy(qread()),tx(qread()),ty(qread());
s=999999;
dfs(sx,sy,tx,ty,0);
cout<<s;
}
可见我有多菜
到了第二天,才发现了这个问题,开始用队列和真正的广搜写这道题,代码如下(搭配注释理解更佳):
#pragma GCC optimize("Ofast","inline","-ffast-math") //编译优化,详见:https://blog.csdn.net/a_n_d_y_s_u_n__/article/details/107658995
#pragma GCC target("abm,avx,mmx,popcnt,sse,sse2,sse3,ssse3,sse4") //编译优化,详见:https://blog.csdn.net/a_n_d_y_s_u_n__/article/details/107658995
#include<iostream>
#include<cstdio>
#include<queue> //队列头文件,详见:https://blog.csdn.net/a_n_d_y_s_u_n__/article/details/119543473
using namespace std;
struct nod { //结构体,方便队列操作
int x,y;
} z,now;
int f[1001][1001],s[1001][1001],n; //f用来存地图,s用来记录到每个点的步数
short dx[4]= {1,-1,0,0}; //用来计算方向
short dy[4]= {0,0,1,-1}; //用来计算方向
bool b[1001][1001]; // 用来判断是否走过,如果走过就不允许再走了
inline int pd(int x,int y) { //用来判断节点是否超出边界,是否已经走过,是否是墙
return x>=1&&x<=n&&y>=1&&y<=n&&f[x][y]==0&&b[x][y]==0;
}
queue<nod> q; //定义队列q,详见https://blog.csdn.net/a_n_d_y_s_u_n__/article/details/119543473
int bfs(int x2,int y2) {
q.push(z); //把结构体z推入队列中(z就是初始位置)
s[z.x][z.y]=0; //到z的步数为0
while(q.size()) { //循环直到队列为空
z=q.front(); //推出队头,赋值给结构体z
q.pop(); //删除队头
if(z.x==x2&&z.y==y2) { //如果已经到了终点就返回步数
return s[x2][y2];
}
int i;
for(i=0; i<4; ++i) { //枚举所有可能的方向
now.x=z.x+dx[i];
now.y=z.y+dy[i];
if(pd(now.x,now.y)) { //判断下一个节点能否进队
b[now.x][now.y]=1; //设置已经走过
s[now.x][now.y]=s[z.x][z.y]+1; //改点步数即为上一个节点的步数+1
q.push(now); //把该节点推入队列,等待下一步处理
}
}
}
}
int main() {
int i,j;
cin>>n;
char c;
for(i=1; i<=n; ++i) { //读入地图
for(j=1; j<=n; ++j) {
c=getchar();
while(c>'9'||c<'0') c=getchar();
f[i][j]=c-'0';
}
}
int x,y,xx,yy;
cin>>z.x>>z.y>>xx>>yy; //读入初始节点和终点的坐标
cout<<bfs(xx,yy); //搜索并输出
}
还有有疑问可以在此处寻找更多优秀文章或者在评论中提出哦~
有帮助的话点个赞再走吧~