寒假预备役周四总结(1.25)

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;

}

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值