1,从周三开始学习bfs,历经两天也算是比较理解bfs(没自信),实现bfs难点应该就在队列的实现,因为没学c++,所以只能用结构体数组实现队列(但是这个结构体数组要开到很大,因为不知道需要多少),下面是学习bfs后写的题
题目链接:P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
解题思路:读完题后就发现这‘马’就是象棋里面的马,走‘日’字形,跟走迷宫一样先把马可以走的所有情况都枚举2出来,判断要不要走出这一步,如果要走出这一步就把这个点入队,否则不入队,然后把到该点的步数算出来,判断该点是否为终点,是终点就结束(因为bfs先找到的终点一定是最小路径),否则继续。遍历整个地图,因为要求出到每一个点的最小步数
代码实现:
#include<stdio.h>
int n,m,x,y;
int b[410][410];//存放起点到某一点的步数同时可以标记某一点走过没有
int dx[10]={-2,-2,2,2,-1,-1,1,1};//马可以走的所有方向的x轴坐标变化
int dy[10]={1,-1,-1,1,2,-2,-2,2};//马可以走的所有方向的y轴坐标变化
struct
{
int x;
int y;
}dl[1000000];//用一个结构体数组来模拟队列
int head=0;//指向对头的一个“指针”
int tail=0;//指向对尾的一个“指针”
void bfs(int x1,int y1)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
b[i][j]=-1;//初始化棋盘为-1,这样就不用判断马到不了某一个点
dl[tail].x=x1;//起点x轴坐标入队
dl[tail++].y=y1;//起点y轴坐标入队,tail++一定不能忘,使尾指针指向头指针的下一个
b[x1][y1]=0;//起点到达起点的步数为0;
while(head!=tail)//判断队列是否为空
{
for(int i=0;i<8;i++)
{
int tx=dl[head].x+dx[i],ty=dl[head].y+dy[i];//枚举马可以走的所有方向
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&b[tx][ty]==-1)//判断该点马是否可走,可走就入队,题目要求找最少步数,所以走过的点就不走了
{
dl[tail].x=tx;
dl[tail++].y=ty;
b[tx][ty]=b[dl[head].x][dl[head].y]+1;//到该点的时间等于到上一个点的时间加上一
}
}
head++;//因为循环里面弹出一个对头,所以新的对头为原对头的下一个元素
}
return ;
}
int main()
{
scanf("%d %d %d %d",&n,&m,&x,&y);
bfs(x,y);//当bfs走完以后棋盘上就附上了起点到某一点的最少步数
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%-5d",b[i][j]);
printf("\n");
}
return 0;
}
题目链接:P1746 离开中山路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
解题思路:和走迷宫一样,从起点出发,依次枚举爱与愁大神能走的四个方向,判断能不能走出这一点,能就入队,不能就判断其他方向,直到走到终点就打印答案,停止搜索
代码实现:
#include<stdio.h>
#define N 1010
int n;
char s[N][N];//存地图并标记该点是否为障碍物或者是否走过
int dx[4]={-1,0,1,0};//爱与愁大神能走的四个方向的x轴坐标
int dy[4]={0,-1,0,1};//爱与愁大神能走的四个方向的x轴坐标
struct{
int x;
int y;
int bu;//到起点距离
}dl[1100000];//结构体数组模拟队列
int head=0,tail=0;//队头指针和队尾指针
void bfs(int x1,int y1,int x2,int y2)//x1,y1为起点,x2,y2为终点
{
dl[tail].x=x1;
dl[tail].y=y1;//起点入队
dl[tail++].bu=0;//起点到起点距离为0,尾指针加一使其指向下一个将要入队的位置
s[x1][y1]='1';//将该点变更成障碍物||标记该点走过
while(head!=tail)//判断对列是否为空
{
for(int i=0;i<4;i++)
{
int tx=dl[head].x+dx[i],ty=dl[head].y+dy[i];//弹出队头,枚举可走的四个方向
if(tx<1||tx>n||ty<1||ty>n||s[tx][ty]=='1')//判断该点不能走
continue;
if(tx==x2&&ty==y2)//判断是否到达终点
{
printf("%d",dl[head].bu+1);
return ;
}
s[tx][ty]='1';//将该点变更成障碍物||标记该点走过
dl[tail].x=tx;
dl[tail].y=ty;
dl[tail++].bu=dl[head].bu+1;//入队,尾指针加一
}
head++;//头指针加一
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);//数组首元素地址加一
int x1,y1,x2,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
bfs(x1,y1,x2,y2);
return 0;
}