基于栈求解迷宫的单条路径和所有路径

news2025/3/12 0:42:18

数据结构与算法课的一个实验,记录一下。

单纯想要了解利用栈求解迷宫的算法可以直接跳转到相应的小标题。

完整代码链接code_2024/mazeLab · LeePlace_OUC/code - 码云 - 开源中国 (gitee.com)

文章目录

      • 要求
      • 栈的实现
      • MazeType类型的组织
      • 迷宫的初始化和销毁
      • 打印路径
      • 单条路径求解
        • 代码实现
        • 测试
      • 所有路径求解
        • 代码实现
        • 测试
      • 对要求中其他点的回答

要求

  1. 基于教材和课件讲解内容,利用自己实现的栈结构完成可运行的迷宫求解程序

  2. 实现教材或课件中未给出的“可通”函数、“足迹打印”函数、“下一位置”函数、“打印不能通过的位置”函数等功能函数

  3. 实现MazeType数据类型,及可能会用到的数据对象(如,入口、出口、位置属性是墙或通路)、数据关系(如,位置之间的相邻关系)、基本操作(如,返回某个坐标位置是墙还是通路)

  4. 测试有通路和没通路等不同结果的输入迷宫

  5. 尝试进一步完善迷宫求解程序,使得从入口到出口有多条简单路径的迷宫的所有路径都能求解出来,或者从多条可行的路径中给出最短路径。

  6. 通过实验结果对比“入口-出口相对方向”和“探索方向的优先顺序”一致或不一致时,迷宫求解程序的运行效率。例如,当出口在入口的右下方向时,探索优先顺序是右下左上,或者上左下右时,程序运行“时间/效率/试过的位置数”是不一样的

  7. 分析“可通”函数原理,解释为什么迷宫求解程序得到的路径不会有环

栈的实现

首先要求实现自己的栈结构,模仿stl库里的stack接口,包含入栈push、出栈pop、获取栈顶元素top、判断栈是否为空empty等基本操作。

// 因为后续入栈的元素类型不确定,所以实现成类模板
template <typename T>
class Stack
{
private:
    T *_stack;
    int _top;
    int _size;
    
public:
    // 默认构造函数,初始容量默认100
    Stack(int size = 100)
        : _size(size), _top(-1)
    {
        _stack = new T[size];
    }

    // 析构函数,直接释放掉开辟的数组空间即可
    ~Stack()
    {
        delete[] _stack;
    }

    // 入栈操作
    void push(const T& x)
    {
        // 首先判断栈是否满了,满了则需要扩容
        if (_top == _size - 1)
        {
            T* newStack = new T[_size * 2];
            for (int i = 0; i < _size; i++)
                newStack[i] = _stack[i];
            delete[] _stack;
            _stack = newStack;
            _size *= 2;
        }
        if (_top < _size - 1)
            _stack[++_top] = x;
    }

    // 出栈,直接top--,当然栈中要有元素
    void pop()
    {
        if (_top >= 0)
            _top--;
    }

    // 获取栈顶元素,直接返回即可
    T& top()
    {
        return _stack[_top];
    }

    // 用top判空
    bool empty()
    {
        return _top == -1;
    }
};

这一步还是很简单的,没什么难度。

MazeType类型的组织

用一个全局的二维数组来存储迷宫,数组元素为0或1,1表示这个位置是墙。

因为需要取路径点进栈,所以需要组织数据结构描述迷宫中的路径点,只需要三个数据成员即可表示,横纵坐标和当前节点的前进方向,所以声明MazeType结构:

struct MazeType
{
    int x;		// 横坐标
    int y;		// 纵坐标
    int dir;	// 方向,0:向右、1:向下、2:向左、3:向上
    
    // 简单的构造函数
    MazeType(int x = 0, int y = 0, int dir = 0)
        : x(x), y(y), dir(dir)
    {}
};

后面用栈求路径时会有几种操作,比如判断当前这个位置是否是终点、是否可通,留下足迹表示这个点走过了,这个点下一步应该走到那个位置,留下足迹表示这个点在当前路径下是不可通的等等。将这些基本操作实现为成员函数。

下面依次进行实现,首先判断是否是终点,很简单,实现一个判断逻辑相等运算符重载即可,后面用的时候直接if (pos == out)

bool operator==(MazeType &a)
{
    return x == a.x && y == a.y;
}

然后是判断是否可通,很简单,只要当前位置在迷宫中的标识是0就是可通的,如果是1则是墙不可通,或者是在栈中的(也会进行相应标识)也不可通:

bool IsPass()
{
    if (maze[x][y] == 0)
        return true;
    return false;
}

然后是留下足迹表示这个点走过了,也就是在栈中:

void FootPrint()
{
    maze[x][y] = dir + 2;
}

这里直接将迷宫中对应位置设置成方向号+2,因为不能和0、1重了,所以直接这样设了,还方便后续直接打印路径。

接下来是求下一个路径点,也很简单,直接根据方向号加减对应坐标即可:

MazeType NextPos()
{
    MazeType next(x, y);
    switch (dir)
    {
    case 0: // 向右,列数加1
        next.y++;
        break;
    case 1: // 向下,行数加1
        next.x++;
        break;
    case 2: // 向左,列数减1
        next.y--;
        break;
    case 3: // 向上,行数减1
        next.x--;
        break;
    }
    return next;
}

最后是留下足迹表示从这个点走下去走不通,这个一般是在路径点所有方向遍历完之后出栈用:

void MakePrint()
{
    maze[x][y] = -1;
}

所以完整的MazeType结构的定义如下:

struct MazeType
{
    int x;
    int y;
    int dir;

    MazeType(int x = 0, int y = 0, int dir = 0)
        : x(x), y(y), dir(dir)
    {}

    bool operator==(MazeType &a)
    {
        return x == a.x && y == a.y;
    }

    bool IsPass()
    {
        if (maze[x][y] == 0)
            return true;
        return false;
    }

    void FootPrint()
    {
        maze[x][y] = dir + 2;
    }

    MazeType NextPos()
    {
        // next的dir直接缺省,默认为0,这个一定要注意,千万不要写成next(x, y, dir)
        // 别问,问就是一开始写错了,debug好久
        MazeType next(x, y);
        switch (dir)
        {
        case 0: // 向右,列数加1
            next.y++;
            break;
        case 1: // 向下,行数加1
            next.x++;
            break;
        case 2: // 向左,列数减1
            next.y--;
            break;
        case 3: // 向上,行数减1
            next.x--;
            break;
        }
        return next;
    }

    void MakePrint()
    {
        maze[x][y] = -1;
    }
};

迷宫的初始化和销毁

这一模块主要是处理输入的,输入格式为迷宫的行号和列号,接下来几行就是0/1迷宫了,加下来两行是起点和终点的坐标,对于这一部分关键变量直接定义成全局的,减少设计参数的负担。

首先是初始化迷宫,对于迷宫的输入,要求不包括边界,边界在代码中手动添加,就是一圈1,这样就不用考虑是否越界的问题了:

int** maze, row, col;

void InitMaze()
{
    cout << "请输入迷宫的行数和列数:";
    cin >> row >> col;

    // 申请空间
    maze = new int*[row + 2];
    for (int i = 0; i < row + 2; i++)
        maze[i] = new int[col + 2];
    
    // 初始化迷宫的边界
    for (int i = 0; i < row + 2; i++)
    {
        maze[i][0] = 1;
        maze[i][col + 1] = 1;
    }
    for (int i = 0; i < col + 2; i++)
    {
        maze[0][i] = 1;
        maze[row + 1][i] = 1;
    }

    // 输入迷宫数据
    cout << "请输入迷宫的数据:" << endl;
    for (int i = 1; i <= row; i++)
        for (int j = 1; j <= col; j++)
            cin >> maze[i][j];
}

对应的是销毁,也就是释放空间:

void DestroyMaze()
{
    for (int i = 0; i < row + 2; i++)
        delete[] maze[i];
    delete[] maze;
}

起点终点的输入处理也在这块写了。终点和起点用两个MazeType对象表示,也设置成全局的:

MazeType in, out;
void InitStartAndEnd()
{
    cout << "请输入起点的坐标:";
    cin >> in.x >> in.y;
    cout << "请输入终点的坐标:";
    cin >> out.x >> out.y;
}

这块对输入的处理均没有考虑容错,假设所有输入都是合法的。

打印路径

为了形象一点,直接把路径从迷宫中标出来,墙用■来表示,如果路径存在的的话用箭头来标识:

void PrintPath()
{
    for (int i = 0; i < row + 2; i++)
    {
        for (int j = 0; j < col + 2; j++)
        {
            if (maze[i][j] == 1)
                cout << "■ ";
            else if (maze[i][j] == 2)
                cout << "→ ";
            else if (maze[i][j] == 3)
                cout << "↓ ";
            else if (maze[i][j] == 4)
                cout << "← ";
            else if (maze[i][j] == 5)
                cout << "↑ ";
            else
                cout << "  ";
        }
        cout << endl;
    }
}

单条路径求解

代码实现

利用栈其实就是dfs。

一开始起始点入栈,然后取栈顶元素作为当前路径点,判断该路径点是否可通,如果可通,则走到下一个点,下一个点入栈,继续重复这个过程。

如果不可通,则需要进行回退,也就是出栈,取新的栈顶元素,也就是上一个点,换一个方向继续走,如果所有 方向都走完了,说明从这个点只会走到死路,留下死路标记,这个点出栈,继续重复。

如果走到了终点就打印路径然后返回,如果走着走着栈为空了,则说明不存在从起点到终点的路径。

明白这个过程代码还是容易写的:

Stack<MazeType> stack;		// 栈对象也定义成全局的
bool MazePath()
{
    MazeType curpos = in;	// curpos表示当前走到的位置,初始化为起点
    int steps = 1;			// steps记录当前探索过的步数,不是实际路径长度
    do						// 用do-while省去初始化步骤
    {
        if (curpos.IsPass())	// 当前位置可通,留下足迹然后找下一个位置
        {
            curpos.FootPrint();	// 留下足迹
            stack.push(curpos);	// 当前位置入栈
            if (curpos == out)	// 走到终点
            {
                cout << "找到路径,一共探索了" << steps << "步:" << endl;
                PrintPath();	// 打印路径
                return true;
            }
            curpos = curpos.NextPos();	// 迭代到下一位置继续
            steps++;		// 探索步数+1
        }
        else				// 当前位置不可通,回溯,需要依次取栈顶元素,也就是上一个点,换方向走
        {
            if (!stack.empty())	// 栈不为空,还有可以换方向的路径点
            {
                MazeType tmp = stack.top();
                stack.pop();
                // 当前路径点的所有方向都走过了,需要标记为死路然后继续取栈顶元素
                while (tmp.dir == 4 && !stack.empty())
                {
                    tmp.MakePrint();
                    tmp = stack.top();
                    stack.pop();
                }
                // 当前路径点还可以变方向,换个方向入栈,然后从新的点继续走
                if (tmp.dir < 4)
                {
                    tmp.dir++;				// 换个方向
                    stack.push(tmp);		// 重新入栈
                    tmp.FootPrint();		// 更新足迹
                    curpos = tmp.NextPos();	// 更新新方向的下一个点
                    steps++;				// 探索步数+1
                }
            }
        }
    } while (!stack.empty());
	// 走到这里说明栈中已经没有路径点了,即起点的四个方向都探索遍了,无路可走
    return false;	
}

这个问题的解空间可以用树来表示,根节点为起点,四个分支,每个分支指向下一个点,然后下一个点又有四个分支…如果用dfs其实是不好求解最短路径的,不过可以求所有路径。求最短路径还得是bfs。

测试

测试代码写在main函数中,如下:

int main()
{
    InitMaze();
    InitStartAndEnd();
    bool flag = MazePath();
    if (!flag)
    {
        cout << "没有找到路径,迷宫无解:" << endl;
        PrintPath();
    }
    DestroyMaze();
    return 0;
}

提供两组测试用例,一组有路径,一组没路径:

13 18
0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 1 0 0 0 0 1 1 1 1 1 0 1
0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 0 0
0 0 0 1 0 0 1 0 0 0 0 1 1 1 1 1 0 0
1 1 1 1 0 0 1 0 0 0 0 1 1 1 1 1 0 1
0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
1 1
13 18

运行如下:
image-20240416223253725

无路径的测试用例:

8 8
0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 1 0 1 1 0 0
0 1 1 1 0 0 0 0
0 1 0 1 0 0 0 0
0 1 0 0 0 1 0 0
0 1 1 1 0 1 1 0
1 0 0 0 0 0 0 0
1 1
8 8

运行如下:
image-20240416223344900

所有路径求解

代码实现

这次测试用例就简化一下,用一个3*3的无墙迷宫:

3 3
0 0 0
0 0 0
0 0 0
1 1
3 3

求所有路径和求单条路径的区别在于当走到终点时,不应直接返回,而是回溯继续走。

如果只考虑到这点,修改代码后跑出来的结果如下:
image-20240416223554442

这其实是因为前面的路径点不会“回头”的原因。比如这个点已经是向下了,那它以后都不会再向右,因为回溯到该点的时候它的方向还是保留的上一条路径中的方向,所以会沿着上一条路径的方向走下去。

比如这个点已经是向下了,那它以后都不会再向右,但实际向右的话还有路。

一个解决方法是找到一条路径后从头再走一遍,但是这样效率极低,并且不好处理相同路径。

换个角度,每个点只会走一次,所有方向走完之后会被设置为死路点,但是在另一条路径中又会走到之前的点。

所以采取在每个点的所有方向都走一遍之后不将其设置为不可通,而改为初始未走过的状态,这样以后还可以走到该点。

给MazeType类型增加一个清除足迹的函数:

void ClearPrint()
{
    maze[x][y] = 0;
}

改进后的MazePath函数如下:

bool flag = false;
Stack<MazeType> stack;
void MazePath()
{
    MazeType curpos = in;
    int steps = 1;
    do
    {
        if (curpos.IsPass())
        {
            curpos.FootPrint();
            stack.push(curpos);
            if (curpos == out)
            {
                flag = true;
                cout << "找到路径,一共探索了" << steps << "步:" << endl;
                PrintPath();
                // 继续寻找其他路径,根节点出栈
                curpos = stack.top();
                stack.pop();
                curpos.ClearPrint();	// 清除根节点的痕迹,保证以后还能走到根节点
                curpos = stack.top();
                curpos.dir++;			// 上一个点换个方向,继续向下走
                steps--;				// 这个是否需要--存疑,不太确定,但还是写了
                continue;				// 不要返回,继续循环
            }
            curpos = curpos.NextPos();
            steps++;
        }
        else
        {
            if (!stack.empty())
            {
                MazeType tmp = stack.top();
                stack.pop();
                while (tmp.dir == 4 && !stack.empty())
                {
                    tmp.ClearPrint();	// 四个方向都走不通,清除足迹
                    tmp = stack.top();
                    stack.pop();
                }
                if (tmp.dir < 4)
                {
                    tmp.dir++;
                    stack.push(tmp);
                    tmp.FootPrint();
                    curpos = tmp.NextPos();
                    steps++;
                }
            }
        }
    } while (!stack.empty());
}

我写完之后其实还是有点怀疑的,毕竟当一个点四个方向都试过时候就清楚它的足迹,这样不会导致死循环吗?

其实结合一下dfs遍历路径树就好理解了,求出所有路径也就是遍历完整颗树时,回到了根节点,此时栈中只剩起点,并且起点的四个方向都走完了,此时清楚其走过的痕迹,然后出栈,接下来栈就空了,循环不会再继续了。

所以如果有路径的话,在求完所有路径之后,循环也就停了。

测试

还是用一开始给的测试用例,结果如下:
image-20240416224604141

用没有路径的用例进行测试,结果也是对的:
image-20240416224628522

对于最短路径,可以在打印的时候统计一下有多少个箭头,箭头的数量就是路径的长度,箭头数最少的那个就是最短路径,可以使用额外的数据结构进行保存,就不展开说了。不推荐用dfs求最短路径。

对要求中其他点的回答

通过实验结果对比“入口-出口相对方向”和“探索方向的优先顺序”一致或不一致时,迷宫求解程序的运行效率。

对这点程序早有准备,使用一个steps变量进行计数,下面使用求单路径的代码进行测试。

我设置的探索优先顺序是右下左上,测试用例提供的起点是(1, 1),终点是(13, 18),为左上到右下,优先级设置的比较合理,不会出现大量的点往上或往左走,上面求得的探索过的次数为486次。

下面将终点和起点反过来,起点在右下,终点在左上。

此时测试结果如下:
image-20240416224956788

结果有点尴尬,竟然更快了。。

显然这还和迷宫的地形有关,沿着右下左上的优先级使中间那一部分点直接沿着墙根走了,所以会快很多。

下面取消所有墙,重新进行几组测试。

测试数据如下:

6 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

第一组:(1,1)->(1,6) vs (1,6)->(1,1):
image-20240416225112161

第二组:(1,1)->(6,6) vs (6,6)->(1,1):
image-20240416225136058

第三组:(3,3)->(4,4) vs (4,4)->(3,3):
image-20240416225150389

可见在排除迷宫结构的因素下,当参照起点和终点的相对位置设置方向优先级时,是可以提高求解效率的。

分析“可通”函数原理,解释为什么迷宫求解程序得到的路径不会有环

可通函数是在maze中该点标记为0才可通,当点入栈之后,标记会变成方向数+2,当四个方向遍历结束后,标记会变成-1,表示在当前探索的路径中该点不可通,所以每个点只会走一次,而如果走出环至少要有一个点走两次,所以在寻找当前这条路径时不会有环。

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

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

相关文章

死磕GMSSL通信-java/Netty系列(二)

死磕GMSSL通信-java/Netty系列(二) 在上一篇文章中,我们探讨了如何利用C/C++实现国密通信。而本文将聚焦于Java环境下,特别是基于Netty框架,如何实现与国密系统的安全通信。为了确保新项目遵循最新的国密标准,我们将优先推荐使用GB/T 38636-2020(TLCP)协议。对于Java开…

python 如何使用windows系统自带的定时功能运行脚本

亲测此定时可以在电脑重启后&#xff0c;仍会自动运行 1.搜索栏搜索‘任务’&#xff0c;打开任务计划程序&#xff0c;点击创建任务 2.写一下任务名称和描述 3.选择触发器&#xff0c;点新建&#xff0c;可以创建定时计划 4.默认只有一次&#xff0c;每天&#xff0c;每月&am…

BackTrader 中文文档(二十七)

原文&#xff1a;www.backtrader.com/ 数据 - 多个时间框架 原文&#xff1a;www.backtrader.com/blog/posts/2015-08-24-data-multitimeframe/data-multitimeframe/ 有时&#xff0c;使用不同的时间框架进行投资决策&#xff1a; 周线用于评估趋势 每日执行进入 或者 5 分钟…

解决 MSYS2 Qt 6.7 默认 stylesheet 在 windows 11 下的显示故障

项目场景&#xff1a; MSYS2 升级到 Qt6.7.0&#xff0c;发现显示故障&#xff0c;所有Qt6程序以及 QtCreator的SpinBox都显示不全&#xff0c;Combox的底色不对。 问题描述 2024年4月1日&#xff0c;pacman升级MSYS2后&#xff0c;Qt6遇到风格错误。如果使用官方的 Qt onlin…

CSS设置内外边距

目录 内边距&#xff08;paddingj&#xff09;&#xff1a; 前言&#xff1a; 设置内边距&#xff1a; 外边距&#xff08;margin&#xff09;&#xff1a; 前言&#xff1a; 设置外边距&#xff1a; 补充(折叠)&#xff1a; 内边距&#xff08;padding&#xff09;&#…

【程序分享】bopcalc 程序:一种评估分子动力学模拟中键序参数的高效方法(二)

分享一篇使用一种评估键序参数的高效程序&#xff1a;bopcalc 。 感谢论文的原作者&#xff01; 主要内容 “ 我们提出了一种新颖、高效的方法来评估键序参数 (BOP)。我们的方法利用球谐函数和 Wigner 符号的特性来减少 BOP 表达式中的项数&#xff0c;并采用归一化关联勒让德…

APP测试基本流程以及APP测试要点梳理,保证您看了不后悔!

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

使用Pandas解决问题:对比两列数据取最大值的五种方法

目录 一、使用max方法 二、使用apply方法结合lambda函数 三、使用np.maximum函数 四、使用clip方法 五、使用where方法结合条件赋值 总结&#xff1a; 在数据处理和分析中&#xff0c;经常需要比较两个或多个列的值&#xff0c;并取其中的最大值。Pandas库作为Python…

前端大屏项目适配方法

要在F11全屏模式下查看 方法一&#xff0c;rem font-size 动态设置HTML根字体大小 和 body 字体大小&#xff08;lib_flexible.js&#xff09; 将设计稿的宽&#xff08;1920&#xff09;平均分成 24 等份&#xff0c; 每一份为 80px。HTML字体大小就设置为 80 px&#xff…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两…

智慧园区可视对讲广播解决方案

智慧园区可视对讲广播解决方案 目前而言智慧园区管理者主要需要解决的问题是&#xff1a; 1.面对庞大的园区小区规模&#xff0c;能源管理全部依赖人工已经无法实现&#xff1b; 2.节能管理工作难度大&#xff0c;面对问题&#xff0c;没有好的解决方案&#xff1b; 3.面临…

详解电源测试系统自定义报告模板功能:如何轻松实现数据导出

在NSAT-8000电源测试系统内&#xff0c;数据一般分为三级架构&#xff1a;原始数据、数据报告和数据分析。数据报告可以直接展示出电源模块的各项测试数据和测试结果&#xff0c;帮助用户评估电源性能&#xff0c;为电源的优化提升提供数据支持。 系统的记录报告板块展示着历史…

油价年内第五涨,92汽油正式进入8元时代

今天是2024年4月16日&#xff0c;最新消息&#xff01;据国家发改委网站16日消息&#xff0c;根据近期国际市场油价变化情况&#xff0c;按照现行成品油价格形成机制&#xff0c;自2024年4月16日24时起&#xff0c;也就是今晚过完的零点开始&#xff0c;国内汽、柴油价格&#…

计算机网络:MAC地址 IP地址 ARP协议

计算机网络&#xff1a;MAC地址 & IP地址 & ARP协议 MAC地址IP地址ARP协议 MAC地址 如果两台主机通过一条链路通信&#xff0c;它们不需要使用地址就可以通信&#xff0c;因为连接在信道上的主机只有他们两个。换句话说&#xff0c;使用点对点信道的数据链路层不需要使…

FR107-ASEMI快恢复二极管FR107

编辑&#xff1a;ll FR107-ASEMI快恢复二极管FR107 型号&#xff1a;FR107 品牌&#xff1a;ASEMI 封装&#xff1a;DO-41 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;1A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;1000V 最大正向电压…

当当图书网数据采集分析:10万条数据的深入洞察

基于搜索结果&#xff0c;我将为您提供一个关于当当图书网数据采集的文章框架&#xff0c;假设我们已经有了10万条数据的采集结果。请注意&#xff0c;由于没有具体的数据文件&#xff0c;以下内容将是一个示例性的框架&#xff0c;您可以根据实际采集到的数据进行填充和调整。…

LeetCode: 209 长度最小的子数组

209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1…

C#创建磁性窗体的方法:创建特殊窗体

目录 一、磁性窗体 二、磁性窗体的实现方法 (1)无标题窗体的移动 (2)Left属性 (3)Top属性 二、设计一个磁性窗体的实例 &#xff08;1&#xff09;资源管理器Resources.Designer.cs设计 &#xff08;2&#xff09;公共类Frm_Play.cs &#xff08;3&#xff09;主窗体 …

【微信小程序之分包】

微信小程序之分包 什么是分包分包的好处分包前的结构图分包后的结构图分包的加载规则分包的体积限制使用分包打包原则引用原则独立分包独立分包的配置方法独立分包的引用原则分包预下载配置分包的预下载分包预下载限制 什么是分包 分包指的是把一个完整小程序项目&#xff0c;…

2016NOIP普及组真题 1. 金币

线上OJ&#xff1a; 一本通&#xff1a;http://ybt.ssoier.cn:8088/problem_show.php?pid1969 核心思想&#xff1a; 解法1、由于数据量只有 10000 天&#xff0c;估可以采用 模拟每一天 的方式。 #include <bits/stdc.h> using namespace std;int k 0;int main() {i…