bfs入门教程(广度优先搜索)(含图解)

news2024/11/16 8:37:47

源自《啊哈算法》 

目录

bfs正文

题目

思路 

完整代码1

完整代码2 

再解炸弹人

题目

思路

完整代码1

完整代码2

总结


bfs正文

第四章--深度优先搜索中,我们用dfs找到了寻找小哈的最短路

接下来,我们要用bfs(Breadth First Search)找到最短路径,并输出最少的步数

 

题目

1,有一天,我的女朋友一个人去玩迷宫,因为方向感很差,迷路了,我得知后马上去解救她

2,迷宫由m行n列的单元格组成(m和n都小于100),每个单元格要么是空地,要么是障碍

3,我的任务是帮助女朋友找到一条从迷宫起点通向女朋友位置的最短路径

4,注意障碍是不能走的,也不能走到迷宫外

思路 

本题中,bfs通过寻找一步以内(相对起点)可以到达的点,两步以内可以到达的点,三步以内....直到找到终点(目标点),或是把所有点都加入队列

 最开始小哼在(1,1)处,上一节dfs中我们的方法是,先让小哼往任意一个可行方向走,然后一直尝试下去,直到走不通就返回这里,这时深度优先,通过递归实现

本节我们通过“一层一层”扩展的方法找到小哈,扩展时每发现一个点,就将这个点加入到队列中,直至走到小哈的位置(p, q)为止 

最开始小哼在入口(1,1)处,一步之内(距离入口)可以到达的点有(1,2)和(2,1)

但小哈不在这两个点上,小哼只能通过(1,2)和(2,1)这两点继续往下走

当小哼走到(1,2),两步之内可以到达的点有(2,2);

当小哼走到(2,1), 两步之内可以到达的点有(2,2)和(3,1)

这时我们发现(2,2)这个点可以通过(1,2)到达,也可以通过(2,1)到达,此时需要一个数组标记某个点是否被访问过 

当然我们可以不需要,可以通过存储迷宫的二维数组直接操作,具体优化代码后面会有

同理,我们找到三步之内可以到达的点有(2,3),(3,2),(4,1)

但是依然没有到达小哈所在点,我们需要重复上述步骤,直到发现小哈

回顾刚才的算法,我们用结构体实现队列来模拟这个过程 

struct note
{
    int x; //横坐标
    int y; //纵坐标
    int s; //步数
};
struct note que[2501]; //地图大小不超过50*50,队列扩展在2500个以内
int head, tail;
int a[51][51] = {0}; //存储迷宫地图
int book[51][51] = {0}; //标记走过的点,防止被重复扩展

//初始化队列
head = 1;
tail = 1;
//先将(1,1)加入队列,并标记
que[tail].x = 1;
que[tail].y = 1;
que[tail].s = 0;
tail++;
book[1][1] = 1;

然后从(1,1)开始,先尝试往右走到达了(1,2)

tx = que[head].x;
ty = que[head].y + 1; //tx, ty为临时变量

需要判断(1,2)是否越界

if(tx < 1 || ty < 1 || tx > m || ty > m)
    continue;

再判断(1,2)是否为障碍或是否走过

if(a[tx][ty] == 0 && book[tx][ty] == 0)

 如果满足上面的条件,将(1,2)入队,并标记该点已经走过

book[tx][ty] = 1;
//注意bfs每个点只入队一次,不需要将book数组取消标记

//插入新的点到队列中
que[tail].x = tx;
que[tail].y = ty;
que[tail].s = que[head].s + 1; //步数是父亲步数 + 1
tail++;

 

 接下来尝试往其他方向走,从(1,1)也可以到达(2,1),所以将(2,1)也加入队列,代码实现与上述一样

 对(1,1)扩展完后,(1,1)就没用了,此时将(1,1)出队,出队操作如下

head++;

 接下来在新扩展出的(1,2)和(2,1)上往下探索,目前为止已扩展出从起点出发,一步以内可以到达的所有点,因为未到达女朋友的位置,所以继续

(1,1)出队后,队列中head指向(1,2),我们需要通过(1,2)继续扩展,通过(1,2)可到达(2,2),将(2,2)也加入队列 

(1,2)扩展完毕,也没用了,就将(1,2)出队. (1,2)出队后,head指向(2,1)这个点. 通过(2,1)可以到达(2,2)和(3,1),但因为(2,2)已经在队列中,因此只将(3,1)入队

截至目前,我们已经扩展出从起点出发两步以内可以到达的所有点,可依旧没到达女朋友的位置,因此继续重复上述步骤,知道遇到小哈,算法结束.

为了方便向四个方向扩展,我们需要一个next数组 

int next[4][2] = {{-1, 0},//上
                  {1, 0}, //下
                  {0, -1},//左
                  {0, 1}};//右

完整代码1

#include<cstdio> //scanf(), printf()
struct note
{
    int x; //横坐标
    int y; //纵坐标
    int f; //父坐标,本题不要求输出路径,不需要
    int s; //步数
};
int main()
{
    struct note que[2501]; //50*50地图,队列扩展不超2500

    int a[51][51] = {0}, book[51][51] = {0};
    int next[4][2] = {{-1, 0}, //上
                      {1, 0},  //下
                      {0, -1}, //左
                      {0, 1}}; //右
    int head, tail;
    int i, j, k, n, m, startx, starty, p, q, tx, ty, flag;

    scanf("%d %d", &n, &m);
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    scanf("%d %d %d %d", &startx, &starty, &p, &q);

    //队列初始化
    head = 1;
    tail = 1;
    //往队列插入迷宫入口坐标
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].s = 0;
    que[tail].f = 0;
    tail++;
    book[startx][starty] = 1;

    flag = 0; //标记是否到达目标点,1表示已到达
    //当队列不为空时
    while(head < tail) {
        //枚举四个方向
        for(k = 0; k <= 3; ++k) {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            //判断越界
            if(tx < 1 || ty < 1 || tx > n || ty > m)
                continue;
            //判断不为障碍且未走过
            if(a[tx][ty] == 0 && book[tx][ty] == 0) {
                //bfs每个点只入队一次
                book[tx][ty] = 1;
                //插入新的点到队列中
                que[tail].x = tx;
                que[tail].y = ty;
                que[tail].f = head; //本题不用
                que[tail].s = que[head].s + 1; //上一步的基础上+1
                tail++; //放最后
            }
            //若达目标点,停止扩展,退出循环
            if(tx == p && ty == q) {
                flag = 1;
                break;
            }
        }
        if(flag) break;
        head++; //继续后续点的扩展
    }
    //tail指向队尾的下一位,所以减1
    printf("%d", que[tail - 1].s);
    return 0;
}
5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3
7

下面是关于去掉book数组的优化,只需在原迷宫数组基础上,把去过的点赋值为-1就好

完整代码2 

#include<cstdio> //scanf(), printf()
struct note
{
    int x; //横坐标
    int y; //纵坐标
    int f; //父坐标,本题不要求输出路径,不需要
    int s; //步数
};
int main()
{
    struct note que[2501]; //50*50地图,队列扩展不超2500

    int a[51][51] = {0};
    int next[4][2] = {{-1, 0}, //上
                      {1, 0},  //下
                      {0, -1}, //左
                      {0, 1}}; //右
    int head, tail;
    int i, j, k, n, m, startx, starty, p, q, tx, ty, flag;

    scanf("%d %d", &n, &m);
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    scanf("%d %d %d %d", &startx, &starty, &p, &q);

    //队列初始化
    head = 1;
    tail = 1;
    //往队列插入迷宫入口坐标
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].s = 0;
    que[tail].f = 0;
    tail++;
    a[startx][starty] = -1;

    flag = 0; //标记是否到达目标点,1表示已到达
    //当队列不为空时
    while(head < tail) {
        //枚举四个方向
        for(k = 0; k <= 3; ++k) {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            //判断越界
            if(tx < 1 || ty < 1 || tx > n || ty > m)
                continue;
            //判断不为障碍且未走过
            if(a[tx][ty] == 0) {
                //bfs每个点只入队一次
                a[tx][ty] = -1;
                //插入新的点到队列中
                que[tail].x = tx;
                que[tail].y = ty;
                que[tail].f = head; //本题不用
                que[tail].s = que[head].s + 1; //上一步的基础上+1
                tail++; //放最后
            }
            //若达目标点,停止扩展,退出循环
            if(tx == p && ty == q) {
                flag = 1;
                break;
            }
        }
        if(flag) break;
        head++; //继续后续点的扩展
    }
    //tail指向队尾的下一位,所以减1
    printf("%d", que[tail - 1].s);
    return 0;
}

输出是一样的,只是把book数组删去,在对应位置上补上a[tx][ty] = 1即可 

再解炸弹人

分别用bfs和dfs解决问题

题目

 还记得小霸王游戏机上的“炸弹人”吗,用放置炸弹的方法来消灭敌人

炸弹的爆炸方向沿上下左右四个方向

问在哪里放置炸弹可以消灭最多的敌人,已知两种墙,一种可以被炸掉

由于现在只有一枚炸弹,所以都用"#"表示(一枚炸弹可以炸掉这种墙,但也会被挡住)

敌人用"G"表示,空地用"."表示,只有空地才能放置炸弹

要求:统计炸弹放在哪个空地上,消灭的敌人最多(上下左右四个方向敌人个数的和)

输出消灭敌人最多的坐标,以及消灭的人数

思路

按照枚举的办法,炸弹放在(1,11)处,最多可消灭11个敌人,注意是从(0,0)开始计算,但小人无法走到(1,11),所以正确答案是放在(7,11)处,可消灭10个敌人

我们使用bfs或dfs(搜索)来枚举出所有小人可以到达的点,然后在这些点分别统计消灭的人数

 

( 先用bfs)

1,起点

小人从点(3,3)开始扩展,先将(3,3)入队,计算出该点可消灭的敌人数量

2,一步以内

通过(3,3)扩展出(2,3),(4,3),(3,2),(3,4),并将这些点入队,再分别计算每个点消灭人数

3,两步以内......

接下来,再通过(2,3)开始扩展......

4,直至所有点扩展完毕,bfs结束,最后输出扩展出的点里,消灭敌人最多的坐标和敌人数量

采用结构体实现队列,需要x, y记录坐标 

struct note
{
    int x, y; //横,纵坐标
};
struct note que[401]; //地图最大20*20,队列扩展最多400
int head, tail;
char a[20][20]; //存储地图

 初始化队列,设置为空(head == tail)

head = 1;
tail = 1;

 队列中插入起始坐标(startx, starty),并标记已在队列中 

que[tail].x = startx;
que[tail].y = starty;
tail++;
a[startx][starty] = -1; //标记已在队列中

 统计炸弹在该点消灭的敌人数量,方法与《啊哈算法》第三章一样《啊哈算法》第三章--枚举很暴力_码龄11天的博客-CSDN博客

此处将某点(i,j)放置炸弹消灭的人数,写成一个函数,函数名为getnum,方便后续调用

sum = getnum(i, j);

 还需要一个next数组便于往四个方向扩展

int next[4][2] = {{-1, 0}, //上
                  {1, 0},  //下
                  {0, -1}, //左
                  {0, 1}}; //右

 接下来开始扩展,也是bfs的核心部分

while(head < tail) {
    //枚举四个方向
    for(k = 0; k < 4; ++k) {
        tx = que[head].x + next[k][0];
        ty = que[head].y + next[k][1];

        //判断越界
        if(tx < 0 || ty < 0 || tx > n - 1 || ty > m - 1)
            continue; //换另一个方向
    
        //未走过的空地
        if(a[tx][ty] == '.') {
            //每个点只入队一次
            a[tx][ty] = -1;
            //插入新扩展的点到队列中
            que[tail].x = tx;
            que[tail].y = ty;
            tail++;
            
            //统计新扩展的点,消灭敌人人数
            sum = getnum(tx, ty);
            //更新max值
            if(sum > max) {
                max = sum;
                mx = tx;
                my = ty;
            }
        }
    }
    head++; //一个点扩展结束后,head++才能对后续点扩展
}

以上就是bfs基本实现过程 

如果换dfs的话,从起点开始,每走到一个新点就统计该点消灭的人数,并从该点继续往后尝试,直到无路可走返回,再尝试其他没走过的方向,直到所有点都访问一遍

void dfs(int x, int y)
{
    int k, sum, tx, ty;
    //计算人数
    sum = getnum(x, y);
    //更新值和坐标
    if(sum > Max)
    { Max = sum; mx = x; my = y; }
    //方向数组
    int next[4][2] = {{-1, 0},{1, 0},{0, -1},{0, 1}};
    //枚举四个方向
    for(k = 0; k < 4; ++k) {
        //下一节点坐标
        tx = x + next[k][0];
        ty = y + next[k][1];
        //判断越界
        if(tx<0 || ty<0 || tx>n-1 || ty>m-1)
            continue;
        //未走过的空地
        if(a[tx][ty] == '.') {
            a[tx][ty] = 'B'; //标记走过
            dfs(tx, ty); //递归
            a[tx][ty] = '.'; //取消标记
        }
    }
    return; //可去掉
}

完整代码1

bfs解题

#include<iostream>
#include<cstdio> //printf()
using namespace std;
struct note
{
    int x, y; //横纵坐标
};
char a[20][20]; //存储地图
int getnum(int i, int j) //统计四个方向的敌人
{
    int sum, x, y;
    sum = 0; //消灭敌人数
    x = i; y = j; //x,y临时变量
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            x--; //向上
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            x++; //向下
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            y--; //向左
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            y++; //向右
    }
    return sum;
}
int main()
{
    struct note que[401]; //20*20地图,队列扩展小于401
    int head, tail;
    int i, j, k, sum, Max = 0, mx, my, n, m, startx, starty, tx, ty;

    //定义方向数组
    int next[4][2] = {{-1,0}, {1,0}, {0,-1},{0,1}};
    cin>>n>>m>>startx>>starty; //n行m列
    for(i = 0; i < n; ++i) cin>>a[i];//读入n行字符

    //队列初始化
    head = 1; tail = 1;
    //插入起始坐标
    que[tail].x = startx;
    que[tail].y = starty;
    tail++;
    a[startx][starty] = 'B'; //标记走过
    Max = getnum(startx, starty); //起点消灭敌人数
    mx = startx; my = starty;
    //当队列不为空
    while(head < tail) {
        //枚举四个方向
        for(k = 0; k < 4; ++k) {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            //判断越界
            if(tx<0 || ty<0 || tx>n-1 || ty > m-1)
                continue;
            //判断未走过的平地
            if(a[tx][ty] == '.') {
                //每个点只入队一次
                a[tx][ty] = 'B'; //标记走过
                //新扩展的点插入队列
                que[tail].x = tx;
                que[tail].y = ty;
                tail++;
                //统计可消灭人数
                sum = getnum(tx, ty);
                //更新Max
                if(sum > Max) {
                    Max = sum;
                    mx = tx;
                    my = ty;
                }
            }
        }
        head++; //继续后面点的扩展
    }
    printf("将炸弹放在(%d, %d)处,可以消灭%d个敌人", mx,my,Max);
    return 0;
}
13 13 3 3
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
将炸弹放在(7, 11)处,可以消灭10个敌人

完整代码2

dfs解题

#include<iostream>
#include<cstdio> //scanf(),printf()
using namespace std;
char a[20][20]; //存储地图
int Max, mx, my, n, m; //声明为全局变量
int getnum(int i, int j) //统计四个方向的敌人
{
    int sum, x, y;
    sum = 0; //消灭敌人数
    x = i; y = j; //x,y临时变量
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            x--; //向上
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            x++; //向下
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            y--; //向左
    }
    x = i; y = j;
    while(a[x][y] != '#') {//不是墙
        if(a[x][y] == 'G') //是敌人
            sum++;
            y++; //向右
    }
    return sum;
}
void dfs(int x, int y)
{
    int k, sum, tx, ty;
    //计算人数
    sum = getnum(x, y);
    //更新值和坐标
    if(sum > Max)
    { Max = sum; mx = x; my = y; }
    //方向数组
    int next[4][2] = {{-1, 0},{1, 0},{0, -1},{0, 1}};
    //枚举四个方向
    for(k = 0; k < 4; ++k) {
        //下一节点坐标
        tx = x + next[k][0];
        ty = y + next[k][1];
        //判断越界
        if(tx<0 || ty<0 || tx>n-1 || ty>m-1)
            continue;
        //未走过的空地
        if(a[tx][ty] == '.') {
            a[tx][ty] = 'B'; //标记走过
            dfs(tx, ty); //递归
            a[tx][ty] = '.'; //取消标记
        }
    }
    return; //可去掉
}
int main()
{
    int i, startx, starty;
    cin>>n>>m>>startx>>starty; //n行m列
    for(i = 0; i < n; ++i) cin>>a[i];//读入n行字符

    a[startx][starty] = 'B';
    Max = getnum(startx, starty);
    mx = startx;
    my = starty;
    dfs(startx, starty);
    printf("炸弹放在(%d, %d),最多消灭%d个敌人",mx,my,Max);
    return 0;
}

输出同上 

总结

bfs核心是扩展,dfs核心是递归

仔细对比,其实本题中,bfs和dfs代码

相同点

1,方向数组next[4][2]        2,getnum()函数得到的消灭人数

区别

bfs构造完getnum()后,直接进入主函数,通过队列和开头的while(head < tail)得到答案

dfs构造完getnum()后,还要构造dfs(),这才进入主函数,然后调用函数得到答案 

bfs的主体是在主函数里通过队列实现的,dfs主体在主函数外通过递归实现 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zookeeper的本地安装部署和分布式安装部署

文章目录一. 本地模式安装部署1&#xff09;安装前准备2&#xff09;配置修改3&#xff09;操作Zookeeper1.2 配置参数解读二. 分布式安装部署1&#xff09;集群规划2&#xff09;解压安装3&#xff09;配置服务器编号4&#xff09;配置zoo.cfg文件5&#xff09;集群操作客户端…

Leetcode.126 单词接龙 II

题目链接 Leetcode.126 单词接龙 II 题目描述 按字典 wordList完成从单词 beginWord到单词 endWord转化&#xff0c;一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk这样的单词序列&#xff0c;并满足&#xff1a; 每对相邻的单词之间…

《高效能团队模式》读书笔记2

如果我们将团队类型的数量缩减为四类基本团队拓扑&#xff0c;这个问题就迎刃而解了。 流动式团队 赋能团队 复杂子系统团队 平台团队只要使用得当&#xff0c;这四类团队拓扑能够满足构建和运行现代软件系统的需要。结合有效的软件边界&#xff08;第6章&#xff09;和团队交互…

Java注解,元注解,自定义注解的使用

Java注解&#xff0c;元注解&#xff0c;自定义注解的使用Java注解基本的注解1.Override2.Deprecated3.SuppressWarnings4.SafeVarargs5.FunctionalInterfaceJava提供的元注解1.Retention2.Target3.Documented4.Inherited自定义注解自定义注解的使用Java注解 从JDK5开始,Java增…

从旺店通·企业奇门到用友U8通过接口集成数据

接入系统&#xff1a;旺店通企业奇门慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算PaaS、SaaS模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c;实现企业规模化发展。对接系统&…

本地数仓项目(四)—— 即席查询

1 背景 本文描述本地数仓项目即席查询相关内容&#xff0c;主要涉及即席查询工具包括Presto、Druid、Kylin。 本文基于文章《本地数据仓库项目(一) —— 本地数仓搭建详细流程》 和《本地数仓项目(二)——搭建系统业务数仓详细流程》以及《本地数仓项目(三&#xff09;—— 数…

金蝶云星辰和旺店通企业版奇门单据接口集成

金蝶云星辰V1和旺店通企业奇门单据接口集成对接源平台:旺店通企业奇门慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算PaaS、SaaS模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c;实…

图的基本概念以及表示方法(链式前向星重点理解,简单易懂版)

图表示一个集合中元素之间存在的多对多关系的一种数据结构。 图的一些定义 &#xff1a; 1.图由顶点和连接顶点的边构成&#xff0c;即G ( V , E ) &#xff0c;其中V为顶点集合&#xff0c;E为边的集合。2.边表示两个顶点之间存在某种关系&#xff0c;边表示为&#xff08;…

Elasticsearch7.8.0版本高级查询—— 单字段排序文档

目录一、初始化文档数据二、单字段排序文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; { "name":"zhangsan", "…

可笑 在网页上复制点东西 还需要money?进来看~

前言 哈喽 大家好&#xff01; 我是木易巷&#xff0c;我回来啦&#xff01;&#xff01;&#xff01; 现在好多平台都变成了不开会员不能复制这样的情况。士可杀不可辱&#xff01;作为一个优秀的复制粘贴工程师&#xff0c;在网页上复制点东西&#xff0c;还需要我掏钱&#…

【Springboot】idea中配置文件不生效、自动提示功能消失、小绿标不出现现象

怎么解决idea中配置文件不生效、自动提示功能消失、小绿标不出现现象先要明确一个核心&#xff0c;就是自动提示功能不是SpringBoot技术给我们提供的&#xff0c;是我们在Idea工具下编程&#xff0c;这个编程工具给我们提供的。明白了这一点后&#xff0c;再来说为什么会出现这…

07.C语言文件操作

1. 使用文件的原因我们前面学习结构体时&#xff0c;写了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&#xff0c;等下…

盒模型 盒子的组成部分 1. 内容 content 2. 填充 (内边距) padding 3. 边框 border 4. 外边距 margin

目录盒模型盒子的组成部分1. 内容 content2. 填充 (内边距) padding3. 边框 border4. 外边距 margin盒模型 box&#xff1a;盒子&#xff0c;每个元素在页面中都会生成一个矩形区域&#xff08;盒子&#xff09; 盒子类型&#xff1a; 行盒&#xff0c;display等于inline的元…

使用Seq2Seq实现中英文翻译

介绍 Deep NLP 自然语言处理NLP是计算机科学、人工智能和语言学交叉领域的分支科学&#xff0c;主要让计算机处理和理解自然语言&#xff0c;如机器翻译、问答系统等。但因其在学习和使用语言的复杂性&#xff0c;通常认为NLP是困难的&#xff0c;近几年&#xff0c;随着深度…

MedCalc:生物医学研究的统计软件 Crack

MedCalc&#xff1a;生物医学研究的统计软件 MedCalc是用于生物医学研究的统计软件包&#xff0c;统计数据包括 220 多个统计测试、程序和图表&#xff0c;ROC曲线分析、方法比较和质量控制工具。 简单易学&#xff0c;快速可靠 MedCalc 包括 220 多种统计测试、程序和图表 RO…

springboot+vue整合JustAuth实现第三方登录

前后端分离版实现第三方登录&#xff1a;GITEE为例 1&#xff1a;首先maven安装依赖&#xff1a; <!-- oauth工具类 --><dependency><groupId>com.xkcoding.justauth</groupId><artifactId>justauth-spring-boot-starter</artifactId><…

学习wifi操作模块simplewifi的基本用法

之前学习Python的过程中学过基于pywifi模块操作wifi连接的用法&#xff0c;在dotnet中&#xff0c;SimpleWifi也支持类似的功能。SimpleWifi是C#语言编写的在Windows系统中管理wifi连接的库&#xff0c;它抽象并封装了Managed Wifi API中的wifi操作相关函数&#xff0c;更易于使…

词向量与语言模型

本篇博客是对于 https://www.cnblogs.com/nickchen121/p/15105048.html#%E7%AC%AC%E4%B8%80%E7%AF%87-transformergptbert%E9%A2%84%E8%AE%AD%E7%BB%83%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F%E7%90%86%E8%AE%BA的归纳 先来了解一…

django,uwsgi,nginx部署配置要点整理

注意&#xff1a; 1.只对关键点进行整理&#xff1a; 2.python_test是项目名称 环境&#xff1a; python:v3.10.9 1.部署前&#xff0c;执行 python manage.py check --deploy 根据提示进行部署检查&#xff0c;调整&#xff0c;ssl相关的可以不做调整 2.settings.py最终版…

Java的类型擦除与泛型的关系

在讨论类型擦除之前&#xff0c;我们必须先来了解一下java的泛型。所谓的泛型就是参数化的类型。这就意思着我们可以具体的类型作为一个参数传递给方法、类、接口。 为什么我们需要泛型呢&#xff1f;首先我们都知道在java里&#xff0c;Object就是对象的父类。Object可以引用…