【路径规划】全局路径规划算法——蚁群算法(含python实现)

news2024/11/25 10:02:11

文章目录

  • 参考资料
  • 1. 简介
  • 2. 基本思想
  • 3. 算法精讲
  • 4. 算法步骤
  • 5. python实现

参考资料

  • 路径规划与轨迹跟踪系列算法
  • 蚁群算法原理及其实现
  • 蚁群算法详解(含例程)
  • 图说蚁群算法(ACO)附源码
  • 蚁群算法Python实现

1. 简介

蚁群算法(Ant Colony Algorithm, ACO) 于1991年首次提出,该算法模拟了自然界中蚂蚁的觅食行为。蚂蚁在寻找食物源时, 会在其经过的路径上释放一种信息素,并能够感知其它蚂蚁释放的信息素。 信息素浓度的大小表征路径的远近信息素浓度越高, 表示对应的路径距离越短。通常, 蚂蚁会以较大的概率优先选择信息素浓度较高的路径, 并释放一定量的信息素, 以增强该条路径上的信息素浓度, 这样,会形成一个正反馈。 最终, 蚂蚁能够找到一条从巢穴到食物源的最佳路径, 即距离最短。

2. 基本思想

  • 用蚂蚁的行走路径表示待优化问题的可行解, 整个蚂蚁群体的所有路径构成待优化问题的解空间
  • 路径较的蚂蚁释放的信息素量较, 随着时间的推进, 较短的路径上累积的信息素浓度逐渐增高, 选择该路径的蚂蚁个数也愈来愈多。
  • 最终, 整个蚂蚁会在正反馈的作用下集中到最佳的路径上, 此时对应的便是待优化问题的最优解。

3. 算法精讲

不失一般性,我们定义一个具有N个节点的有权图 G = ( N , A ) G=(N,A) G=(N,A),其中N表示节点集合 N = 1 , 2 , . . . , n N={1,2,...,n} N=1,2,...,n,A表示边, A = ( i , j ) ∣ i , j ∈ N A={(i,j)|i,j\in N} A=(i,j)i,jN。节点之间的距离(权重)设为 ( d i j ) n × n (d_{ij})_{n\times n} (dij)n×n目标函数即最小化起点到终点的距离之和。

  • 设整个蚂蚊群体中蚂蚊的数量为 m m m, 路径节点的数量为 n n n, 节点 i i i 与节点 j j j 之间的相互距离为 d i j ( i , j = 1 , 2 , … , n ) , t d_{i j}(i, j=1,2, \ldots, n), t dij(i,j=1,2,,n),t时刻节点 i i i 与节点 j j j 连接路径上的信息素浓度为 τ i j ( t ) \tau_{i j}(t) τij(t) 。初始时刻, 各个节点间连接路径上的信息素浓度相同, 不妨设为 τ i j ( 0 ) = τ 0 \tau_{i j}(0)=\tau_{0} τij(0)=τ0

  • 蚂蚁 k ( k = 1 , 2 , … , m ) k(k=1,2, \ldots, m) k(k=1,2,,m) 根据各个节点间连接路径上的信息素浓度决定其下一个访问节点, 设 P i j k ( t ) P_{i j}^{k}(t) Pijk(t) 表示 t t t 时刻蚂蚊 k k k 从节点 i i i 转移到节点 j j j 的概率, 其计算公式如下:
    P i j k = { [ τ i j ( t ) ] α ⋅ [ η i j ( t ) ] β ∑ s ∈  allow  k [ τ i s ( t ) ] α ⋅ [ η i s ( t ) ] β s ∈  allow  k 0 s ∉  allow  k (1) \tag{1} P_{i j}^{k}= \begin{cases}\frac{\left[\tau_{i j}(t)\right]^{\alpha} \cdot\left[\eta_{i j}(t)\right]^{\beta}}{\sum_{s \in \text { allow }_{k}}\left[\tau_{i s}(t)\right]^{\alpha} \cdot\left[\eta_{i s}(t)\right]^{\beta}} & s \in \text { allow }_{k} \\ 0 & s \notin \text { allow }_{k}\end{cases} Pijk=s allow k[τis(t)]α[ηis(t)]β[τij(t)]α[ηij(t)]β0s allow ks/ allow k(1)

    其中,

    • η i j ( t ) \eta_{i j}(t) ηij(t)启发函数, η i j ( t ) = 1 / d i j \eta_{i j}(t)=1 / d_{i j} ηij(t)=1/dij, 表示蚂蚊从节点 i i i 转移到节点 j j j 的期望程度,
    • a l l o w k ( k = 1 , 2 , … , m ) allow_{k}(k=1,2, \ldots, m) allowk(k=1,2,,m) 为蚂蚁 k k k待访问节点的集合。开始时, a l l o w k allow_{k} allowk中有(n-1)个元素,即包括除了蚂蚁 k k k出发节点的其它所有节点。随着时间的推进, allow k _{k} k 中的元素不断减少, 直至为空, 即表示所有的节点均访问完毕。
    • α \alpha α信息素重要程度因子, 其值越大, 蚂蚁选择之前走过的路径可能性就越大,搜索路径的随机性减弱, 其值越小,蚁群搜索范围就会减少,容易陷入局部最优。一般取值范围为 [ 0 , 5 ] [0,5] [0,5]
    • β \beta β启发函数重要程度因子, 其值越大, 表示启发函数在转移中的作用越大, 即蚂蚊会以较大的摡率转移到距离短的节点,蚁群就越容易选择局部较短路径,这时算法的收敛速度是加快了,但是随机性却不高,容易得到局部的相对最优。一般取值范围为 [ 0 , 5 ] [0,5] [0,5]
  • 计算完节点间的转移概率后,采用与遗传算法中一样的轮盘赌方法选择下一个待访问的节点。

    依据轮盘赌法来选择下一个待访问的节点, 而不是直接按概率大小选择,是因为这样可以扩大搜索范围,进而寻找全局最优,避免陷入局部最优。

    首先计算每个个体的累积概率 q j q_{j} qj ,如下式:
    q j = ∑ j = 1 l P i j k (2) \tag{2} q_{j}=\sum_{j=1}^{l} P_{i j}^{k} qj=j=1lPijk(2)
    q j q_{j} qj 相当于转盘上的跨度,跨度越大的区域越容易选到, l l l代表下一步可选路径的数量。
    之后随机生成一个 ( 0 , 1 ) (0 , 1) (01) 的小数 r \mathrm{r} r,比较所有 q j q_{j} qj r \mathrm{r} r 的大小,选出大于 r r r 的最小的那个 q j , q_{j} , qj q j q_{j} qj 对应的索引 j j j即为第 k \mathrm{k} k 只蚂蚁在第 i i i条路径时下一步要选择的目标点。
    r = rand ⁡ ( 0 , 1 ) j = index ⁡ { min ⁡ [ q j > r ] } (3) \tag{3} \begin{gathered} r=\operatorname{rand}(0,1) \\ j=\operatorname{index}\left\{\min \left[q_{j}>r\right]\right\} \end{gathered} r=rand(0,1)j=index{min[qj>r]}(3)

  • 在蚂蚁释放信息素的同时,各个节点间连接路径上的信息素逐渐消失,设参数 ρ ( 0 < ρ < 1 , 一 般 取 值 为 0.1 \rho(0<\rho<1,一般取值为0.1 ρ(0<ρ<10.1~ 0.99 ) 0.99) 0.99)表示 信息素的挥发程度。当所有的蚂蚁完成一次循环后,各个节点间链接路径上的信息素浓度需进行更新,计算公式为
    { τ i j ( t + 1 ) = ( 1 − ρ ) τ i j ( t ) + Δ τ i j Δ τ i j = ∑ k = 1 n Δ τ i j k (4) \tag{4} \left\{\begin{array}{l} \tau_{i j}(t+1)=(1-\rho) \tau_{i j}(t)+\Delta \tau_{i j} \\ \Delta \tau_{i j}=\sum_{k=1}^{n} \Delta \tau_{i j}^{k} \end{array}\right. {τij(t+1)=(1ρ)τij(t)+ΔτijΔτij=k=1nΔτijk(4)
    其中, Δ τ i j k \Delta \tau_{i j}^{k} Δτijk表示第 k k k只蚂蚁在节点 i i i与节点 j j j连接路径上释放的信息素浓度; Δ τ i j \Delta \tau_{i j} Δτij表示所有蚂蚁在节点 i i i与节点 j j j连接路径上释放的信息素浓度之和。

  • 蚂蚁信息素更新的模型包括蚁周模型(Ant-Cycle模型)、蚁量模型(Ant-Quantity模型)、蚁密模型(Ant-Density模型)等。

    区别:

    1. 蚁周模型利用的是全局信息,即蚂蚁完成一个循环后更新所有路径上的信息素;

    2. 蚁量和蚁密模型利用的是局部信息,即蚂蚁完成一步后更新路径上的信息素。

    信息素增量不同信息素更新时刻不同信息素更新形式不同
    蚁周模型信息素增量为 Q / L k Q/L_k Q/Lk,它只与搜索路线有关与具体的路径(i,j)无关在第k只蚂蚁完成一次路径搜索后,对线路上所有路径进行信息素的更新信息素增量与本次搜索的整体线路有关,因此属于全局信息更新
    蚁量模型信息素增量为 Q / d i j Q/d_{ij} Q/dij,与路径(i,j)的长度有关在蚁群前进过程中进行,蚂蚁每完成一步移动后更新该路径上的信息素利用蚂蚁所走路径上的信息进行更新,因此属于局部信息更新
    蚁密模型信息素增量为固定值Q在蚁群前进过程中进行,蚂蚁每完成一步移动后更新该路径上的信息素利用蚂蚁所走路径上的信息进行更新,因此属于局部信息更新

    蚁周模型的 Δ τ i j k \Delta \tau_{i j}^{k} Δτijk计算公式如下
    Δ τ i j k = { Q / L k ,  第  k  只蚂蚁从城市  i  访问城市  j 0 ,  其他  (5) \tag{5} \Delta \tau_{i j}^{k}= \begin{cases}Q / L_{k}, & \text { 第 } \mathrm{k} \text { 只蚂蚁从城市 } \mathrm{i} \text { 访问城市 } \mathrm{j} \\ 0, & \text { 其他 }\end{cases} Δτijk={Q/Lk,0,  k 只蚂蚁从城市 i 访问城市 j 其他 (5)
    式中 Q Q Q为信息素常数(一个正的常数),表示蚂蚁循环一次所释放的信息素总量。 L k L_{k} Lk为第k只蚂蚁经过路径的总长度。

4. 算法步骤

  1. 对相关参数进行初始化,如蚁群规模(蚂蚁数量) m m m、信息素重要程度因子 α \alpha α、启发函数重要程度因子 β \beta β、信息素挥发因子 ρ \rho ρ、信息素常数 Q Q Q、最大迭代次数 i t e r m a x itermax itermax

  2. 构建解空间,将各个蚂蚁随机地置于不同的出发点,为每只蚂蚁确定当前候选道路集

  3. 更新信息素计算每个蚂蚁经过路径长度 L k ( k = 1 , 2 , … , m ) L_k(k=1,2,…,m) Lk(k=1,2,m),记录当前迭代次数中的最优解(最短路径)。同时,对各个节点连接路径上信息素浓度进行更新。

  4. 判断是否终止若 i t e r < i t e r m a x iter<itermax iter<itermax,则令 i t e r = i t e r + 1 iter=iter+1 iter=iter+1,清空蚂蚁经过路径的记录表,并返回步骤2;否则,终止计算,输出最优解。

5. python实现

使用蚁群算法解决旅行商问题(TSP),代码来自博客。

import numpy as np
import matplotlib.pyplot as plt


# 城市坐标(52个城市)
coordinates = np.array([[565.0,575.0],[25.0,185.0],[345.0,750.0],[945.0,685.0],[845.0,655.0],
            [880.0,660.0],[25.0,230.0],[525.0,1000.0],[580.0,1175.0],[650.0,1130.0],
            [1605.0,620.0],[1220.0,580.0],[1465.0,200.0],[1530.0,  5.0],[845.0,680.0],
            [725.0,370.0],[145.0,665.0],[415.0,635.0],[510.0,875.0],[560.0,365.0],
            [300.0,465.0],[520.0,585.0],[480.0,415.0],[835.0,625.0],[975.0,580.0],
            [1215.0,245.0],[1320.0,315.0],[1250.0,400.0],[660.0,180.0],[410.0,250.0],
            [420.0,555.0],[575.0,665.0],[1150.0,1160.0],[700.0,580.0],[685.0,595.0],
            [685.0,610.0],[770.0,610.0],[795.0,645.0],[720.0,635.0],[760.0,650.0],
            [475.0,960.0],[95.0,260.0],[875.0,920.0],[700.0,500.0],[555.0,815.0],
            [830.0,485.0],[1170.0, 65.0],[830.0,610.0],[605.0,625.0],[595.0,360.0],
            [1340.0,725.0],[1740.0,245.0]])

def getdistmat(coordinates):
    num = coordinates.shape[0]
    distmat = np.zeros((52, 52))
    for i in range(num):
        for j in range(i, num):
            distmat[i][j] = distmat[j][i] = np.linalg.norm(
                coordinates[i] - coordinates[j])
    return distmat


# #//初始化
distmat = getdistmat(coordinates)
numant = 45 ##// 蚂蚁个数
numcity = coordinates.shape[0] ##// 城市个数
alpha = 1 ##// 信息素重要程度因子
beta = 5 ##// 启发函数重要程度因子
rho = 0.1 ##// 信息素的挥发速度
Q = 1 ##//信息素释放总量
iter = 0##//循环次数
itermax = 200#//循环最大值
etatable = 1.0 / (distmat + np.diag([1e10] * numcity)) #// 启发函数矩阵,表示蚂蚁从城市i转移到矩阵j的期望程度
pheromonetable = np.ones((numcity, numcity)) #// 信息素矩阵
pathtable = np.zeros((numant, numcity)).astype(int) #// 路径记录表
distmat = getdistmat(coordinates) #// 城市的距离矩阵
lengthaver = np.zeros(itermax) #// 各代路径的平均长度
lengthbest = np.zeros(itermax) #// 各代及其之前遇到的最佳路径长度
pathbest = np.zeros((itermax, numcity)) #// 各代及其之前遇到的最佳路径长度
#//核心点-循环迭代
while iter < itermax:
    #// 随机产生各个蚂蚁的起点城市
    if numant <= numcity:
        #// 城市数比蚂蚁数多
        pathtable[:, 0] = np.random.permutation(range(0, numcity))[:numant]
    else:
        #// 蚂蚁数比城市数多,需要补足
        pathtable[:numcity, 0] = np.random.permutation(range(0, numcity))[:]
        pathtable[numcity:, 0] = np.random.permutation(range(0, numcity))[
            :numant - numcity]
    length = np.zeros(numant)  # 计算各个蚂蚁的路径距离
    for i in range(numant):
        visiting = pathtable[i, 0]  # 当前所在的城市
        unvisited = set(range(numcity))  # 未访问的城市,以集合的形式存储{}
        unvisited.remove(visiting)  # 删除元素;利用集合的remove方法删除存储的数据内容
        for j in range(1, numcity):  # 循环numcity-1次,访问剩余的numcity-1个城市
            # 每次用轮盘法选择下一个要访问的城市
            listunvisited = list(unvisited)
            probtrans = np.zeros(len(listunvisited))
            for k in range(len(listunvisited)):
                probtrans[k] = np.power(pheromonetable[visiting][listunvisited[k]], alpha) \
                    * np.power(etatable[visiting][listunvisited[k]], beta)
            cumsumprobtrans = (probtrans / sum(probtrans)).cumsum()
            cumsumprobtrans -= np.random.rand()
            k = listunvisited[(np.where(cumsumprobtrans > 0)[0])[0]]
            # 元素的提取(也就是下一轮选的城市)
            pathtable[i, j] = k  # 添加到路径表中(也就是蚂蚁走过的路径)
            unvisited.remove(k)  # 然后在为访问城市set中remove()删除掉该城市
            length[i] += distmat[visiting][k]
            visiting = k
        # 蚂蚁的路径距离包括最后一个城市和第一个城市的距离
        length[i] += distmat[visiting][pathtable[i, 0]]
        # 包含所有蚂蚁的一个迭代结束后,统计本次迭代的若干统计参数
    lengthaver[iter] = length.mean()
    if iter == 0:
        lengthbest[iter] = length.min()
        pathbest[iter] = pathtable[length.argmin()].copy()
    else:
        if length.min() > lengthbest[iter - 1]:
            lengthbest[iter] = lengthbest[iter - 1]
            pathbest[iter] = pathbest[iter - 1].copy()
        else:
            lengthbest[iter] = length.min()
            pathbest[iter] = pathtable[length.argmin()].copy()
    # 更新信息素
    changepheromonetable = np.zeros((numcity, numcity))
    for i in range(numant):
        for j in range(numcity - 1):
            changepheromonetable[pathtable[i, j]][pathtable[i, j + 1]] += Q / distmat[pathtable[i, j]][
                pathtable[i, j + 1]]  # 计算信息素增量
        changepheromonetable[pathtable[i, j + 1]][pathtable[i, 0]] += Q / distmat[pathtable[i, j + 1]][pathtable[i, 0]]
    pheromonetable = (1 - rho) * pheromonetable + \
        changepheromonetable  # 计算信息素公式
    if iter%30==0:
        print("iter(迭代次数):", iter)
    iter += 1  # 迭代次数指示器+1

# 做出平均路径长度和最优路径长度
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 10))
axes[0].plot(lengthaver, 'k', marker=u'')
axes[0].set_title('Average Length')
axes[0].set_xlabel(u'iteration')

axes[1].plot(lengthbest, 'k', marker=u'')
axes[1].set_title('Best Length')
axes[1].set_xlabel(u'iteration')
fig.savefig('average_best.png', dpi=500, bbox_inches='tight')
plt.show()

# 作出找到的最优路径图
bestpath = pathbest[-1]
plt.plot(coordinates[:, 0], coordinates[:, 1], 'r.', marker=u'$\cdot$')
plt.xlim([-100, 2000])
plt.ylim([-100, 1500])

for i in range(numcity - 1):
    m = int(bestpath[i])
    n = int(bestpath[i + 1])
    plt.plot([coordinates[m][0], coordinates[n][0]], [
             coordinates[m][1], coordinates[n][1]], 'k')
plt.plot([coordinates[int(bestpath[0])][0], coordinates[int(n)][0]],
         [coordinates[int(bestpath[0])][1], coordinates[int(n)][1]], 'b')
ax = plt.gca()
ax.set_title("Best Path")
ax.set_xlabel('X axis')
ax.set_ylabel('Y_axis')

plt.savefig('best path.png', dpi=500, bbox_inches='tight')
plt.show()

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

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

相关文章

mybatis-plus 自动填充的时间跟真实时间相差8小时

项目中 用到了以下两个字段,分别是插入数据时间和更新数据时间&#xff0c;用的mybatis-plus自动填充,结果发现填充的时间跟真实时间相差很多。查了一些资料&#xff0c;找到了解决方案&#xff1a; 1. 下图是我的mysql没有进行配置之前的时区配置,这里的CST包括了4个时区,分别…

一百零六、Hive312的计算引擎由MapReduce(默认)改为Spark(亲测有效)

一、Hive引擎包括&#xff1a;默认MR、tez、spark 在低版本的hive中&#xff0c;只有两种计算引擎mr, tez 在高版本的hive中&#xff0c;有三种计算引擎mr, spark, tez 二、Hive on Spark和Spark on Hive的区别 Hive on Spark&#xff1a;Hive既存储元数据又负责SQL的解析&…

【0基础】学习solidity开发智能合约-初识solidity

本篇课程开始&#xff0c;我们来学习一下如何使用solidity开发智能合约&#xff0c;由于博主对于solidity的学习&#xff0c;也是自学的&#xff0c;所以一些不足或有纰漏之处还望指出&#xff0c;大家共同进步&#xff0c;本系列课程会分很多节课讲述&#xff0c;从入门到进阶…

安装navicat详细流程

1.双击已下载好的navicat安装包&#xff0c;点击"下一步" 2.点击我同意&#xff0c;在点击"下一步" 3.设置navicat安装路劲&#xff0c; 至少要保证磁盘有90M的空间。在这里选择默认的安装路径&#xff0c;也可以根据自身情况安装到其他盘。 4.默认&#x…

一个几乎全民都会的算法——二分查找

为什么说二分查找是全民都会的算法&#xff1f; 20年前央视2套有一档叫《幸运52》的综艺节目&#xff0c;其中一个环节叫《幸运超市》&#xff0c;每一期已故著名主持人咏哥都会给佳宾们出示几个商品&#xff0c;凡是佳宾猜中价格的&#xff0c;就能获赠这件商品。这档节目红极…

C++ 类和对象(中)构造函数 和 析构函数 ,const成员

上篇链接&#xff1a;C 类和对象&#xff08;上&#xff09;_chihiro1122的博客-CSDN博客 类的6个默认成员函数 我们在C当中&#xff0c;在写一些函数的时候&#xff0c;比如在栈的例子&#xff1a; 如上述例子&#xff0c;用C 返回这个栈是否为空&#xff0c;直接返回的话&am…

Selenium+Pytest自动化测试框架实战

前言 1、Selenium是一个免费的(开源)自动化测试组件&#xff0c;适用于跨不同浏览器和平台的Web应用程序【selenium是一个自动化工具&#xff0c;而不是自动化框架】。它非常类似于HP Quick Test Pro (QTP现在叫UFT)&#xff0c;只是Selenium侧重于自动化基于Web的应用程序。使…

初、高中生到底该不该学习编程?

从小学&#xff0c;到初中&#xff0c;再到高中&#xff0c;知识的提升主要体现在一个方面上&#xff0c;就是知识越来越抽象了。很多孩子在初中成绩还可以&#xff0c;到了高中就跟不上了&#xff0c;这是最主要的一个原因。 编程主要就是要求学习它的人&#xff0c;有较强的…

2023武生院计科专升本指南

自我介绍一下&#xff0c;我叫啊超&#xff0c;22级专升本上岸武生院考了211的计应学长&#xff0c;社恐&#xff0c;不善言辞&#xff0c;出门都走下水道&#xff0c;吃饭因社恐&#xff0c;屡次不敢买单。单身可撩&#xff0c;哈哈哈~ 我只是提出自己的一些个人建议&#xff…

utittest和pytest中mock的使用详细介绍

Mock是Python中一个用于支持单元测试的库&#xff0c;它的主要功能是使用mock对象替代掉指定的Python对象&#xff0c;以达到模拟对象的行为。 python3.3 以前&#xff0c;mock是第三方库&#xff0c;需要安装之后才能使用。python3.3之后&#xff0c;mock作为标准库内置到 un…

防火墙(firewall)

前言 计算机的安全性历来就是人们热衷的话题之一。而随着Internet的广泛应用&#xff0c;人们在扩展了获取和发布能力的同时也带来信息被污染和破坏的危险。这些安全问题主要是由网络的开放性、无边界性、自由性造成的&#xff0c;还包括以下一些因素。 1. 计算机操作系统本身…

分布式补充技术 01.AOP技术

01.AOP技术是对于面向对象编程&#xff08;OOP&#xff09;的补充。是按照OCP原则进行的编写&#xff0c;(ocp是修改模块权限不行&#xff0c;扩充可以) 02.写一个例子&#xff1a; 创建一个新的java项目&#xff0c;在main主启动类中&#xff0c;写如下代码。 package com.co…

CTSI 基金会储备透明度报告——2023 年 1 月

由于 Cartesi 代币 (CTSI) 的下一次解锁定于 2023 年 1 月 23 日&#xff0c;我们很高兴接着上一份透明度报告&#xff0c;我们本次依旧提供关于 Cartesi 基金会的治理、运营以及 CTSI 代币如何分配的另一份官方透明度报告。 提醒一下&#xff0c;为了保证诚实和可信度&#xf…

软件测试工程师简历项目经验怎么写

软件测试工程师简历项目经验怎么写 面试是我们进入一个公司的门槛&#xff0c;通过了面试才能进入公司&#xff0c;你的面试结果和你的薪资是息息相关的。 在面试之前&#xff0c;不得不聊聊简历&#xff0c;简历是职场的敲门砖&#xff0c;是拿到offer的通行证&#xff0c;那么…

【unity学习记录-场景绘制+物体碰撞,场景物体的层级关系】跟着Unity2D官方入门教程 Ruby‘ Adventure

文章目录 创建tilemap编辑一下资源&#xff0c;瓦片调色对于瓦片没有填满的情况&#xff0c;调整每片瓦片的像素 添加点小树或其他&#xff0c;调整层级给树木增加一些碰撞的效果&#xff0c;调整碰撞范围&#xff0c;角色也要添加刚体人物倒着走路的解决方法&#xff08;解决角…

线程与进程,你真得理解了吗

线程与进程&#xff0c;你真得理解了吗 1 进程与线程的关系和区别2 并行与并发3 线程共享了进程哪些资源 相信大家面试时一定没少被一个问题刁难&#xff0c;那就是进程和线程的区别是什么&#xff1f;这个问题延申开来并不像表面那么简单&#xff0c;今天就来深入一探。 开始…

个人简历html网页代码(使用chatgpt完成web开发课的实验)

使用chatgpt完成web开发课的实验 前提&#xff1a; chatgpt的使用&#xff0c;建议看https://juejin.cn/post/7198097078005841980或者自己随便找 要学会用“出国旅游”软件 vscode的基本使用 炼丹开始&#xff1a; 炼丹材料&#xff1a; 帮我写一个html页面&#xff0c;内…

沁恒 CH32V208(四): CH32V208 网络DHCP示例代码分析

目录 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置沁恒 CH32V208(二): CH32V208的储存结构, 启动模式和时钟沁恒 CH32V208(三): CH32V208 Ubuntu22.04 Makefile VSCode环境配置沁恒 CH32V208(四): CH32V208 网络DHCP示例代码分析 硬件部分 CH32V208WBU6 …

Python 网络爬虫与数据采集(一)

Python 网络爬虫与数据采集 第1章 序章 网络爬虫基础1 爬虫基本概述1.1 爬虫是什么1.2 爬虫可以做什么1.3 爬虫的分类1.4 爬虫的基本流程1.4.1 浏览网页的流程1.4.2 爬虫的基本流程 1.5 爬虫与反爬虫1.5.1 爬虫的攻与防1.5.2 常见的反爬与反反爬 1.6 爬虫的合法性与 robots 协议…

深入理解Java虚拟机:JVM高级特性与最佳实践-总结-3

深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践-总结-3 垃圾收集器与内存分配策略垃圾收集算法标记-清除算法标记-复制算法标记-整理算法 垃圾收集器与内存分配策略 垃圾收集算法 标记-清除算法 最基础的垃圾收集算法是“标记-清除”&#xff08;Mark-Sweep&#xff…