资讯动态

粒子群算法多无人机任务分配源码解析与Python实现

发布时间:2026/10/26 15:56:16 来源:尧图企业网站定制
简介面向毕业设计、课程设计与期末大作业等场景提供一套基于Python的粒子群算法多无人机任务分配实现适合需要快速搭建智能优化算法演示项目的开发者。压缩包共15个文件其中包含9个Python脚本覆盖问题建模、距离与适应度计算、PSO主流程、结果解码及绘图等功能另有4张PNG仿真结果图、1份Markdown说明文档整体大小仅1.41MB结构清晰、便于阅读和二次修改。目前已有72人学习下载项目源码经过严格测试可直接用于课程提交或二次开发。代码内含完整算法与可视化模块既能帮助理解粒子群优化原理也能直接作为多无人机任务分配课程的验收材料或毕业设计展示内容README文档对模块功能做了梳理能够在现有项目基础上扩展新的约束与求解策略。1. 粒子群算法多无人机任务分配拿到源码后第一步是看懂建模而不是跑通代码“基于 Python 开发的粒子群算法多无人机任务分配源码”这种标题在毕业设计和课程设计里出镜率很高。多数人拿到压缩包第一件事就是跑 main.py跑通了就以为完事结果答辩时老师问一句“粒子维度为什么等于任务数”“续航惩罚系数怎么定的”就卡住。这个方向的实质不是粒子群算法本身——标准 PSO 主循环用不了 50 行——而是把“哪架无人机去执行哪个任务”变成粒子编码再写目标函数、压住硬约束。它适合正在做毕设、课设或项目开发的从业者先理解建模后面代码和实验才有根基。这篇笔记会按建模、编码、主循环、改进、避坑、验证的顺序把整个方案讲成可以直接落地的步骤。2. 把任务分配“翻译”成粒子目标函数、硬约束与三种编码方式2.1 任务分配问题的数学形式N 架无人机对 M 个任务变量怎么定多无人机任务分配的常见设定是有 N 架无人机、M 个待执行任务每架无人机从不同起点出发速度、最大航程可能不同每个任务有地理位置部分任务带时间窗。要决策的是把任务分给哪些无人机以及单架无人机内部按什么顺序执行。评价指标通常是总飞行距离最短、整体完成时间最小或尽可能多地完成高优先级任务。毕设和课设里最常用的是“总航程最短 续航约束”因为这个组合最容易出图表也最好讲解。用数组表达是这样无人机集合 U{1..N}任务集合 T{1..M}决策变量 x_{ij} 表示任务 j 是否分配给无人机 i。直接拿二维矩阵当粒子并不合适矩阵会引入“一个任务同时被两架无人机选中”“某架无人机空着”这类大量无效组合粒子群在黑匣子里搜索效率会很难看。更常见的做法是把决策压成一维每个任务 j 对应一个取值这个值的含义是“任务 j 由编号几的无人机执行”。一维向量天然满足任务唯一性也符合粒子群“每个粒子是一个解”的直觉。目标函数一般写成所有无人机完成各自任务序列的总航程也可在总航程上再加一个最大完成时间项用权重平衡。用公式表达为 F Σ_i sum(seq_i 上的相邻点距离)其中 seq_i 是第 i 架无人机的任务执行顺序。如果题目强调“整体完成时间最短”就把所有无人机完成时间的最大值纳入目标乘以一个权重。这里要特别留意一维分配向量只决定“任务归谁”每架无人机按什么顺序飞还需要二次求解。常见做法是最近邻贪心从起点开始每次挑最近的任务代码量小、运行快视觉上也说得过去。如果题目要求同时优化分配和顺序那就得换两段式编码复杂度会上一个量级对课程设计通常没有必要。2.2 硬约束清单续航、时间窗、任务唯一性哪些必须进适应度无论用什么编码有三类约束会反复出现在题目和评分标准里。任务唯一性每个任务最多被执行一次。一维映射编码天然满足这是选它的核心原因。续航约束单架无人机累计航程不能超过最大航程这条必须在适应度函数里处理否则粒子会收敛出“一架无人机飞完全部任务”的极端解。时间窗约束部分任务要求在某个时间区间内开始执行时间窗一旦转成硬约束就很麻烦因为标准粒子群是连续优化算法处理离散的“必须在 10:00 到 10:30 到达”逻辑很别扭通常也转成惩罚项。这三条里唯一性靠编码兜底续航和时间窗靠惩罚或修复。注意不要把全部约束交给惩罚系数罚太小粒子无所谓罚太大粒子全部跑进“不做任务”的局部最优。这个平衡问题是后面第 5 章要展开的“玄学”现场。实际项目中我一般把续航和完成率一起输出报告里同时写“总航程 178.6完成率 100%”比只写一个无惩罚的 fitness 数字可信很多。2.3 三种粒子编码方式对比离散整数、连续映射和置换序列在建模阶段就要决定粒子用什么编码。我见过的主流方案有三种。第一种是直接离散整数编码粒子每个维度直接取 0..N-1 的整数值表示任务 j 被分配给无人机 i。最直观但标准 PSO 的速度更新公式算出来是浮点数必须取整离散化很多教程直接 round会导致大量粒子落在同一个整数上种群多样性快速下降。第二种是连续实数映射编码。粒子维度取 [0,1) 的实数解码时乘无人机数量 N 后向下取整得到无人机编号。这个方案保留了 PSO 连续搜索的优势是一维编码里最值得照抄的形式。第三种是置换序列编码把 M 个任务排成全排列再用若干断点切分成 N 段每段分给一架无人机。这种编码能同时表达“分给谁”和“按什么顺序做”实现时又要额外维护断点位置粒子维度不稳定调试成本高适合研究型课题。三个方案放在一起对比选择就清晰了编码方式粒子维度是否天然满足任务唯一性能否表达单机顺序适合场景离散整数编码M需要额外约束修复否演示、快速原型连续实数映射编码M是否毕业设计、课程设计首选置换序列断点MN-1是是研究型项目、有充分调试时间一句话记忆粒子群算法擅长连续、光滑的浮点空间整数空间会把 PSO 变成随机枚举。既然手里有连续映射这种稳妥方案就不要用取整硬上。2.4 距离矩阵怎么组织一个索引约定牵动全部代码无人机起点和任务点要放在同一个坐标系里计算距离最终生成一个 (NM) x (NM) 的方阵叫 dist_mat。索引约定必须统一前 N 行是无人机起点后 M 行是任务点。也就是说任务 t 在 dist_mat 里的真实行号是 n_uav t。这个约定贯穿整个解码、适应度和结果输出过程一旦写错程序不报错但算出来的总航程完全错误。很多翻车现场都出在这个索引上把 dist_mat[cur][t] 写成了 dist_mat[cur][t]忘记了任务点从第 n_uav 行才开始。由于距离矩阵是对称的某些小规模数据下结果只是偏大一点点不容易被察觉换数据或换规模之后结果直接崩。项目开发时我习惯在 main 开头写一行调试输出打印 dist_mat.shape 和 x.shape几秒钟就能排除掉八成索引问题。这个习惯在第 5 章还会用到。3. 用 Python 写出可复现的粒子群任务分配主循环3.1 最小依赖环境只用 numpy 和随机数避免花哨库这里给出的核心代码可以放进一个空工程直接跑不需要除了 numpy 以外的第三方库。有的教程会引入 pyswarm、deap 或 matplotlib 做演示但对毕设源码来说外部依赖越少答辩现场换机器跑崩的概率越低。装 numpy 的方式是 pip install numpy如果你的环境里已经有 Anaconda通常不需要再装。在写代码之前先固定随机种子。粒子群是一个随机优化算法不固定种子的话每次运行结果都会有波动固定种子一方面方便你调参对比另一方面避免老师现场跑两次结果不一致的尴尬。固定种子放主程序入口而不是放在函数内部。import numpy as np # 固定随机种子保证每次运行结果可复现 np.random.seed(42)固定种子之后整个算法里所有 np.random 调用都会按同一套序列走。如果你想测试“不同初始种群的稳定性”可以用 seed 42 run_id 的方式做多次独立运行这个技巧在第 6 章还会用到。3.2 初始化无人机与任务生成距离矩阵的数据结构先定义问题规模。为了演示我通常生成一个 20 x 20 的二维平面5 架无人机、10 个任务并随机生成位置。在实际项目里这个位置数据可以换成经纬度或园区坐标只要替换生成逻辑后面的距离计算不用动。距离矩阵是这段代码的核心产物。它的形状是 (NM, NM)dist[i][j] 表示节点 i 到节点 j 的欧氏距离。为了单机内部排序还需要任务到任务的距离所以一次性生成完整方阵再在计算时切片。N_UAV 5 # 无人机数量 N_TASK 10 # 任务数量 MAP_SIZE 20.0 # 地图边长 # 随机生成无人机起点和任务位置第一段是无人机后面是任务 nodes np.random.rand(N_UAV N_TASK, 2) * MAP_SIZE uav_pos nodes[:N_UAV] # shape: (5, 2) task_pos nodes[N_UAV:] # shape: (10, 2) # 全量距离矩阵前 N_UAV 行是无人机起点后 N_TASK 行是任务位置 dist_mat np.zeros((N_UAV N_TASK, N_UAV N_TASK)) for i in range(N_UAV N_TASK): for j in range(N_UAV N_TASK): if i ! j: dist_mat[i][j] np.linalg.norm(nodes[i] - nodes[j])这段代码里dist_mat 的行列索引含义必须统一索引 0..N_UAV-1 是无人机起点N_UAV..N_UAVN_TASK-1 是任务点。后面 decode 和适应度计算都靠这个索引约定。很多翻车现场就是索引写岔了结果算出来单机航程为零但总距离很小看起来“最优”实际根本没有执行任务。3.3 PSO 主循环速度更新、边界裁剪与全局最优更新标准粒子群速度更新公式不多解释v wv c1r1*(pbest - x) c2r2(gbest - x)。关键是几个参数在一开始就要给足惯性权重 w 取大一点保证前期探索c1、c2 取 1.5 到 2.0 的常见区间。这里给一组稳定的默认值w 0.8c1 1.8c2 1.8种群 60迭代 200。边界处理不用太复杂。因为粒子每个维度代表连续映射值合法区间就是 [0, 1)越界直接 clip 回去即可。这样做虽然损失了一部分原 PSO 的“越界反弹”特性但任务分配问题边界并不敏感clip 最简单可靠。def pso_task_alloc(dist_mat, n_uav, n_task, pop_size60, max_iter200, w0.8, c11.8, c21.8): dim n_task low, high 0.0, 1.0 # 种群位置和速度 x np.random.uniform(low, high, (pop_size, dim)) v np.random.uniform(-0.1, 0.1, (pop_size, dim)) pbest x.copy() pbest_fit np.array([fitness(ind, dist_mat, n_uav, n_task) for ind in x]) gbest_idx np.argmin(pbest_fit) gbest pbest[gbest_idx].copy() gbest_fit pbest_fit[gbest_idx] for it in range(max_iter): for i in range(pop_size): r1 np.random.rand(dim) r2 np.random.rand(dim) v[i] w * v[i] c1 * r1 * (pbest[i] - x[i]) c2 * r2 * (gbest - x[i]) x[i] v[i] x[i] np.clip(x[i], low, high) fit fitness(x[i], dist_mat, n_uav, n_task) if fit pbest_fit[i]: pbest_fit[i] fit pbest[i] x[i].copy() gbest_idx np.argmin(pbest_fit) if pbest_fit[gbest_idx] gbest_fit: gbest pbest[gbest_idx].copy() gbest_fit pbest_fit[gbest_idx] return gbest, gbest_fit提示pbest 和 gbest 赋值务必使用 copy()否则后续 x 更新时gbest 的引用会跟着变全局最优永远停在初始值附近。这是 PSO 实现里最常见的隐蔽坑。几个细节是血泪经验速度初始化不要太大取 -0.1 到 0.1位置在 [0,1) 区间内太大的初速度会让粒子飞出去再被 clip 回来浪费迭代次数。收敛判据这里用的是最大迭代次数工程上可以加一个“连续 30 代 gbest 没变化就提前停”的逻辑能在答辩演示时省时间。3.4 解码与适应度给每个任务找无人机再算总飞行距离前面提到连续映射解码每个任务的维度实数乘无人机数量向下取整得到无人机编号。这里要小心一个边界条件当某个值恰好等于 1.0 时乘以 N_UAV 后取整可能得到 N_UAV而合法编号只能到 N_UAV-1所以要 clip 一下。def decode(x, n_uav): # x: (n_task,)每个值在[0,1)之间 assign (x * n_uav).astype(int) assign np.clip(assign, 0, n_uav - 1) return assign解码之后得到一个长度为 N_TASK 的数组 assignment[j] i表示任务 j 分配给无人机 i。接下来的适应度计算分三步第一步按无人机分组取出它负责的任务第二步用之前生成的 dist_mat 片段做单机最近邻排序算单机航程第三步把所有单机航程加总再对超续航的方案施加惩罚。def fitness(x, dist_mat, n_uav, n_task): assign decode(x, n_uav) total_dist 0.0 uav_tasks {i: [] for i in range(n_uav)} for j, uav in enumerate(assign): uav_tasks[uav].append(j) for i, tasks in uav_tasks.items(): if not tasks: continue route [i] # 起点是无人机 i 自身 remain list(tasks) # 最近邻依次挑最近的任务点访问 while remain: cur route[-1] dists [dist_mat[cur][n_uav t] for t in remain] nxt remain[int(np.argmin(dists))] route.append(n_uav nxt) remain.remove(nxt) # 最后飞回起点 route.append(i) single sum(dist_mat[route[k]][route[k 1]] for k in range(len(route) - 1)) total_dist single return total_dist注意 dist_mat 索引里任务 t 在 dist_mat 中的真实行号是 n_uav t。这一点非常容易漏距离矩阵是无人机起点和任务点拼在一起的直接写 dist_mat[cur][t] 会把任务号当成矩阵行号得到完全错误的结果。最近邻排序是贪心不是最优顺序但对任务分配阶段的适应度排序足够如果你希望更精确可以把这一段替换成动态规划或可复用 TSP 求解器。3.5 跑起来主程序、随机种子与结果导出把上面函数整合到一个 main 里跑一次完整的分配并打印结果。这里再放一个结果导出逻辑输出每架无人机的任务序列和总航程。对于毕设报告这个输出可以直接粘进实验结果章节。if __name__ __main__: np.random.seed(42) # 前面 3.2 已生成 N_UAV、N_TASK、dist_mat 等变量 best_x, best_fit pso_task_alloc(dist_mat, N_UAV, N_TASK) assign decode(best_x, N_UAV) print(最优适应度(总航程):, round(best_fit, 2)) for uav in range(N_UAV): tasks [j for j, a in enumerate(assign) if a uav] print(fUAV{uav}: 任务序列 {tasks})主程序如果只想看最终结果建议同时打印每次迭代的 gbest_fit 曲线数据。要实现这个在 pso_task_alloc 里加一行 history.append(gbest_fit) 即可。曲线数据保存成 txt 或 csv后面画图时直接读取不用重跑算法。这是项目开发里常见的“先留证据再补图表”的做法。4. 从能跑到“敢答辩”三种让分配结果更稳的改进策略4.1 续航违约的惩罚函数惩罚系数怎么定才不翻车如果完全不管续航PSO 很容易找到“让一架无人机飞完全部任务”的极端解——总距离可能确实最小但航程远远超出实际能力。惩罚函数是最直接的硬约束处理在 fitness 末尾加上超出部分乘系数。PENALTY 50.0 endurance np.array([100.0] * n_uav) # 每架无人机最大航程 # 在 3.4 的 fitness 循环里对每架无人机的 single 做检查 # for i, single in enumerate(...): if single endurance[i]: total_dist (single - endurance[i]) * PENALTY惩罚系数最忌拍脑袋。如果距离量级是 50 到 200而惩罚系数只有 0.1那超出的 100 距离只罚 10粒子完全不在乎如果系数是 5000那所有粒子都会优先找“少做任务”的方案结果每架无人机都在家门口转圈。我一般先完全不罚跑一次看 fitness 的平均量级然后取量级的 2 到 5 倍作为惩罚系数。通过运行两三次就能落到稳定区间这就是“先量纲、后数值”的调参流程。4.2 修复优先于惩罚超续航任务重新分配保证方案合法惩罚函数的问题是只能“引导”不能保证最终解合法。如果你的评分标准要求“最终方案必须全部在续航内”就需要在解码之后、算适应度之前做修复。修复逻辑不复杂先算每架无人机的航程找到超续航的那架把它航程末尾的任务拿出来重新分配给离该任务最近且加装之后不超续航的另一架无人机如果所有无人机都无法接收就把这个任务标记为“未执行”。这样得到的解一定满足续航约束缺点是每次修复都会改变分配PSO 在连续空间中的梯度信息被破坏了收敛速度会慢一些。更工程化的做法是“惩罚 修复结合”粒子群迭代阶段用惩罚函数引导速度方向算法结束后对最优解做一次修复保证展示时拿到的方案严格合法。这样既保证了收敛性又保证最终结果能通过规则检查。这一招很多项目里都会用但你几乎看不到有人写进论文。4.3 惯性权重线性递减别让一个 w 参数毁掉整个算法标准 PSO 的 w 是常数这有个问题固定的大 w 让粒子一直高速探索后期收不住固定的小 w 收敛快但很容易一头扎进局部最优。最实用的改进是对 w 做线性递减让粒子前期到处飞后期集中在最优解附近精修。w_max, w_min 0.9, 0.4 for it in range(max_iter): w w_max - (w_max - w_min) * it / max_iter # 速度更新时使用当前 w参数含义w_max 取 0.9 是 PSO 文献里的经典值能保证前期有足够探索能力w_min 取 0.4 表示后期仍保留 40% 的惯性避免过快地陷入停滞。若任务规模小于 10可以把迭代上限减小到 150当任务数大于 50建议迭代 400 起步。注意 w 递减的范围不宜过窄0.8 到 0.6 这种区间基本起不到“前期探索、后期开采”的分段作用。4.4 差粒子变异与重启最简单有效的防早熟手段线性递减 w 还有一个短板如果前 30 代粒子都已经聚集到某个局部最优附近后面 w 再小也救不回来。一个简单粗暴的手段是每过一定代数找出适应度最差的一部分粒子把它们重新初始化或做随机扰动。这个操作相当于给种群打强心针。if it % 50 0: worst_idx np.argsort(pbest_fit)[-int(0.2 * pop_size):] for idx in worst_idx: x[idx] np.random.uniform(low, high, dim) v[idx] np.random.uniform(-0.1, 0.1, dim) pbest_fit[idx] fitness(x[idx], dist_mat, n_uav, n_task) pbest[idx] x[idx].copy()这段代码在每 50 代把最差的 20% 粒子重置。变异比例 20% 不要设太大否则种群容易从稳定收敛变成随机搜索也不要太频繁建议每 30 到 50 代触发一次。注意重置后要立刻更新 pbest_fit不然下一次循环 gbest 计算可能读到陈旧的适应度值。加了变异之后迭代曲线会出现周期性的跳变这是正常现象不等于算法坏了。看到曲线终于不再“一路平”反而说明这一点奏效了。4.5 怎么判断改进真的有效看收敛曲线的三种形态改进是否有效不是“跑一次结果变好了”能证明的。把每次迭代的 gbest_fit 存下来画成收敛曲线常见三种形态第一类是曲线在一二十代内陡降后立刻水平说明种群迅速同质化改进策略还没有发挥作用第二类是曲线持续缓慢下降直到迭代结束也没有明显水平说明迭代次数不够可以加长 max_iter第三类是曲线下降中出现周期性小幅回升这正是变异策略在重置差粒子属于正常现象。判断改进有效要看曲线最终平稳值是否明显低于原版 PSO且在更换随机种子后仍然保持。5. 粒子群多无人机任务分配源码的五个高频坑与排查5.1 粒子维度设成无人机数量解码越界现象一运行就报 index out of bounds或者生成的分配结果里所有任务都堆到编号最大的无人机上。原因把 dim 设为 N_UAV而正确的维度应当是任务数 N_TASK。粒子群每个维度对应一个任务维度上的取值决定这个任务由哪架无人机执行。解决初始化 x np.random.uniform(0, 1, (pop_size, n_task))。如果是从别人源码改来的记得把解码函数里的乘 n_uav 和维度定义同时改掉两个位置不一致时最容易出现“不报错但结果很怪”。5.2 全局最优一直是初始值变量引用没拷贝现象迭代了很多代gbest_fit 纹丝不动但单步打印 pbest 却在变。原因gbest pbest[idx] 直接把 pbest[idx] 的引用赋给 gbest之后 pbest[idx] 被更新成新位置gbest 也同步变了全局最优永远停留在初始值附近。解决统一用 gbest pbest[idx].copy()pbest[i] x[i].copy()。这是 PSO 实现里最容易犯也最难排查的引用坑。排查方法是在速度更新前打印 gbest 的值看它是否随迭代意外变化。5.3 所有粒子收成同一个局部最优现象迭代曲线前 20 代下降很快之后 100 代几乎不动解的出现位置也很相似。原因初始化时全体粒子都挤在 [0,1) 中部加上 c1、c2 偏大社会学习分量太强种群快速同质化。解决初始化时用 np.random.uniform(0.1, 0.9) 拉开间距并把 c2 降到 1.5 左右给个人认知更多分量。也可以叠加第 4 章的变异手段定期重置差粒子。要判断是否真的早熟可以打印每一代所有粒子的平均适应度如果平均值和全局最优一样低说明种群已经失去多样性。5.4 惩罚系数拍脑袋分配结果全是“不执行任务”现象最终方案里大量任务没有分配出去总距离很小但整体完成率低得没法看。原因惩罚系数过大导致任何超续航方案都变成天价粒子从不可行区域直接被推回“每架无人机都只做一个任务”的解。PENALTY 从 100 改到 10000结果天差地别这就是最常见的“玄学”现场。解决先统计一次不罚分时的平均航程和最大航程惩罚系数设为平均航程的 2~5 倍。并且把完成率写入输出最后报告的指标要同时看距离和完成率不要只看 fitness 降了多少。5.5 换了机器跑结果全部错乱numpy 广播与索引问题现象同一份源码在自己的电脑上正常换台电脑或换 numpy 版本后结果出现 NaN 或任务索引错位。原因常见有两类。一类是 dist_mat 索引写成 dist_mat[cur][t]而 t 是任务编号没有加上 n_uav 偏移当数据规模恰好某种特殊组合时偏差不明显但换数据就崩。另一类是 numpy 版本差异下x * n_uav 对二维数组的广播行为不同如果 x 的 shape 是 (pop_size, 1) 而不是 (pop_size, n_task)乘出来是 (pop_size, pop_size) 的诡异矩阵。解决在解码函数里加上形状断言 assert x.shape (n_task,)对 dist_mat 访问统一用 n_uav t。跑代码前可以在 main 开头打印 dist_mat.shape 和 x.shape几秒钟就能排除掉八成索引问题。6. 验证分配结果可靠性的一个技巧基线对比与 20 次独立运行6.1 贪心基线给 PSO 一个“下限”粒子群是随机优化算法答辩现场最怕被问“再跑一次还是这个结果吗”。我的习惯是每次实验都同时算一条贪心基线依次把每个任务分配给当前最近的无人机再把超续航的任务移除。贪心法没有搜索过程结果通常比 PSO 差但它是“下限”。真正说服人的不是“适应度 187.6”而是“比贪心低 23%20 次独立运行的标准差只有 3.1”。def greedy_assign(dist_mat, n_uav, n_task): assign np.zeros(n_task, dtypeint) for j in range(n_task): dists [dist_mat[i][n_uav j] for i in range(n_uav)] assign[j] int(np.argmin(dists)) return assign注意这段贪心不处理航程约束所以只作为“不做搜索”的下限对比时最好把 PSO 的完成率也统计出来。贪心基线的代码价值不在性能在于提供一个可复现的比较对象。6.2 多次独立运行报告里最有说服力的三行数字固定种子可以复现但只给一个固定种子的结果会被质疑“是不是挑出来的”。正确做法是把种子从 100 到 119 跑 20 次记录每次的最优适应度再输出平均值、最优值和标准差。best_list [] for run in range(20): np.random.seed(100 run) best_x, best_fit pso_task_alloc(dist_mat, N_UAV, N_TASK) best_list.append(best_fit) print(20次平均:, round(np.mean(best_list), 2)) print(20次最优:, round(np.min(best_list), 2)) print(标准差:, round(np.std(best_list), 2))标准差小说明算法稳定性好平均最优值低说明搜索能力强这两个数字放进论文比十页伪代码更有说服力。把每次运行的前期数据画成叠加收敛曲线还能直观看到多次运行之间的波动范围这是毕设报告里最出效果的一张图。最后照例讲一个教训。我做这类项目时曾经花了一整天调参数终于在某组数据上把结果刷得很漂亮结果换成另一组随机生成的无人机起点后方案直接退化得不如贪心。后来才明白这不是算法的问题而是我把参数“背”进了那组数据。现在每次调参完我都会换两到三组随机地图重新验一遍确认改进不是运气才敢写进结论。这个习惯后来又帮我在项目交付里避免了至少一次返工。希望这些建模、编码和排查的经验能帮到你把粒子群多无人机任务分配源码真正跑通、跑稳毕业设计、课程设计和项目开发里的这个方向就不会再绕远路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑