动态规划入门:0/1背包问题核心原理与代码实现详解
1. 背包问题从新手到精通的必经之路如果你刚开始接触算法尤其是动态规划那么“0/1背包问题”绝对是你绕不开的一座大山也是检验你是否真正理解动态规划思想的绝佳试金石。我见过太多朋友一看到“状态转移方程”这几个字就开始头疼代码写出来要么超时要么结果不对最后只能对着别人的题解“复制粘贴”过几天又忘得一干二净。这其实是因为没有把背包问题的“骨架”和“灵魂”吃透。今天我们就抛开那些让人眼花缭乱的公式和抽象定义用最直白的话、最详细的步骤和一眼就能看懂的图示把0/1背包问题从里到外拆解清楚。我们的目标不止是让你看懂一道题而是帮你建立起解决一整类动态规划问题的思维框架。你会发现一旦掌握了这个核心模型很多所谓的难题比如分割等和子集、目标和、一和零都不过是换了一件“马甲”的背包问题。2. 问题本质一个关于选择的经典模型在深入代码之前我们必须先搞清楚我们在解决一个什么问题。想象一下这个场景你有一个最大承重为W的背包面前摆着N件物品。每件物品i都有两个属性重量weight[i]和价值value[i]。现在你要从这些物品中挑选一些放进背包目标很简单——在背包能装得下的前提下总重量不超过W让你选中的物品总价值尽可能高。这就是0/1背包问题。“0/1”这个名字非常形象它意味着每件物品只有两种命运要么被选中状态为1要么被放弃状态为0。你不能把一件物品拆开只拿一半。这种“非此即彼”的特性是后续我们设计算法时最关键的约束。注意很多人容易混淆“背包容量”和“物品重量”的单位。在实际解题中我们通常假设它们都是整数。如果题目给出的是小数一般可以通过乘以一个倍数转化为整数处理这是算法题中常见的技巧。那么最直接的暴力解法是什么枚举所有可能的物品组合。对于每件物品都有“选”或“不选”两种可能N件物品就有2^N种组合。我们检查每种组合的总重量是否超载在不超载的组合中找出价值最高的那个。当N稍微大一点比如30组合数就超过10亿了计算机也算不过来。所以暴力法行不通我们必须寻找更聪明的办法这就是动态规划登场的时候。3. 动态规划解法的核心状态与选择动态规划之所以高效是因为它“记住”了过去的计算结果避免了重复劳动。它的核心思想可以概括为“过去的状态决定了现在的选择现在的选择构成了未来的状态”。对于背包问题我们需要定义清楚什么是“状态”以及怎么做“选择”。3.1 定义状态数组dp我们定义一个二维数组dp[i][j]。这个数组的含义是整个理解过程的基石请务必牢记dp[i][j]表示从前i件物品物品编号从0到 i-1中进行选择在背包容量恰好为j的情况下能够获得的最大价值。这里有三个关键点需要解释“前 i 件物品”这代表我们决策的范围。i从0到N当i0时意味着没有任何物品可选。“容量恰好为 j”这是一种非常经典且严谨的定义方式。它要求我们最终装满的背包总重量正好是j。与之相对的另一种定义是“容量不超过 j”两种定义在初始化时略有不同但核心转移逻辑相通。我们先从“恰好”这个更清晰的定义入手。“最大价值”这是我们最终要优化的目标。3.2 状态转移方程决策的艺术现在我们站在dp[i][j]这个状态上思考我们已经处理完了前i-1件物品现在面对第i-1号物品因为我们的i是从0开始计数的前i件物品的索引是0到i-1我们要做出选择。对于第i-1件物品我们只有两种选择不放入背包那么当前的最大价值完全等同于不考虑这件物品时的最大价值也就是dp[i-1][j]。因为背包容量j没变我们只是跳过了这件物品。放入背包前提是背包容量j必须大于等于这件物品的重量weight[i-1]。如果放入那么背包会消耗掉weight[i-1]的容量剩下的容量是j - weight[i-1]。这部分剩余容量在前i-1件物品中能创造的最大价值是dp[i-1][j - weight[i-1]]。再加上当前物品的价值value[i-1]总价值就是dp[i-1][j - weight[i-1]] value[i-1]。我们的目标是价值最大所以在这两种选择中取最大值。因此状态转移方程就诞生了如果 j weight[i-1]: dp[i][j] max(dp[i-1][j], dp[i-1][j - weight[i-1]] value[i-1]) 否则 dp[i][j] dp[i-1][j] // 放不下只能不选这个方程就是动态规划解决背包问题的“心脏”。它清晰地告诉我们当前状态的最优解完全由之前已经计算出的、更小的子问题的最优解推导而来。3.3 图文解析一步步推演让我们用一个具体的例子把上面的过程画出来这是理解动态规划最直观的方式。假设有4件物品背包容量W8。 物品信息如下物品编号重量 (weight)价值 (value)023134245356我们初始化一个dp[5][9]的表格i从0到4共5行j从0到8共9列。根据“恰好装满”的定义我们初始化dp[0][0] 0表示没有物品、容量为0时最大价值为0。而dp[0][j] (j0)则初始化为一个“不可能”的值比如负无穷 (-inf)因为用0件物品不可能装满任何正数的容量。在实际代码中我们常用一个非常小的负数来代表。现在开始填表i1(处理物品0)j 2放不下dp[1][j] dp[0][j] -inf(除了j0)。j 2可以选择放或不放。不放dp[0][2] -inf放dp[0][0] 3 0 3 3取最大值max(-inf, 3) 3。所以dp[1][2] 3。 同理dp[1][3]...dp[1][8]在j2时因为dp[0][j]都是-inf所以最大值都是来自“放入”的选择。例如dp[1][8] dp[0][6] 3 -inf 3但dp[0][6]是-inf这里有个关键当j - weight[i-1]对应的状态是“不可能”时“放入”这个选择本身也是不可能的。所以我们需要在代码中处理这种情况。为了简化理解我们换一种更常用的初始化“容量不超过j”。在这种定义下dp[i][j]表示前i件物品在容量不超过j时的最大价值。此时dp[0][j] 0因为不放任何物品价值总是0且不会超容量。这样更直观。让我们用“不超过”的定义重新表述和填表。状态定义dp[i][j]表示从前i件物品中选择总重量不超过j的最大价值。初始化dp[0][j] 0。转移方程dp[i][j] max(dp[i-1][j], dp[i-1][j - weight[i-1]] value[i-1])(当j weight[i-1])否则dp[i][j] dp[i-1][j]。填表过程部分i0行全是0。i1(处理物品0重2价3):j0,1: 容量小于2放不下dp[1][j] dp[0][j] 0。j2:max(dp[0][2]0, dp[0][0]33) 3。j3:max(dp[0][3]0, dp[0][1]33) 3。...j8:max(dp[0][8]0, dp[0][6]33) 3。规律一旦j大于等于物品重量从该j开始往后所有dp[1][j]都至少是3因为我们可以选择放入物品0。i2(处理物品1重3价4):j0,1,2: 容量小于3放不下物品1继承上一行dp[2][j] dp[1][j]。j3: 可以不放(dp[1][3]3)或者放(dp[1][0]4044)。max(3,4)4。j4: 不放(dp[1][4]3)放(dp[1][1]4044)。max(3,4)4。j5: 不放(dp[1][5]3)放(dp[1][2]4347)。max(3,7)7。注意这里得到了价值7它是物品0和物品1的组合重量235价值347。j8: 不放(dp[1][8]3)放(dp[1][5]4347)。max(3,7)7。通过这样一步步填表最终dp[4][8]就是我们的答案。这个过程就像是在有限的资源和多种选择中不断做出局部最优的决策并记录下结果最终汇聚成全局最优解。图表能清晰地展示每个状态是如何从左上角或正上方的状态转移而来强烈建议你在学习时亲手画一遍这个表格。4. 代码实现与空间优化从二维到一维的飞跃理解了状态转移代码实现就是水到渠成。我们先写出最直观的二维DP版本。4.1 基础二维DP实现def knapsack_2d(weight, value, capacity): n len(weight) # 初始化dp表大小为 (n1) x (capacity1) dp [[0] * (capacity 1) for _ in range(n 1)] # 开始状态转移 for i in range(1, n 1): # i从1到n代表前i件物品 w_i, v_i weight[i-1], value[i-1] # 当前物品的重量和价值 for j in range(capacity 1): # j从0到capacity代表当前背包容量 if j w_i: # 当前背包容量装不下第i件物品 dp[i][j] dp[i-1][j] else: # 装得下决策不装 vs 装 dp[i][j] max(dp[i-1][j], dp[i-1][j - w_i] v_i) # 最终结果存储在dp[n][capacity] return dp[n][capacity] # 测试用例 weight [2, 3, 4, 5] value [3, 4, 5, 6] capacity 8 print(knapsack_2d(weight, value, capacity)) # 输出应为 10 (物品13 重量358价值4610)这个版本非常清晰完全对应了我们上面的推导。但是它有一个问题空间复杂度是O(N*W)。当背包容量很大时比如W10000这个二维数组会占用很多内存。观察状态转移方程dp[i][j] max(dp[i-1][j], dp[i-1][j - w_i] v_i)你会发现计算dp[i][j]时只用到了上一行 (i-1) 的数据并且是上一行中j列以及j-w_i列的数据。这意味着我们并不需要保存整个二维表格只需要一个一维数组滚动更新就够了。4.2 优化为一维DP滚动数组我们把二维数组dp[i][j]压缩成一维数组dp[j]。在计算第i件物品时dp[j]在更新之前存储的其实就是dp[i-1][j]的值。那么状态转移就变成了dp[j] max(dp[j], dp[j - w_i] v_i)。这里有一个至关重要的细节内层循环必须从大到小遍历j。 为什么因为dp[j - w_i]需要的是“上一轮” (i-1时) 的结果。如果我们从小到大遍历j那么在计算dp[j]时dp[j - w_i]可能已经被“当前轮” (i时) 更新过了这就变成了dp[i][j - w_i]而不是我们需要的dp[i-1][j - w_i]这相当于同一件物品被多次放入这解决的是“完全背包”问题而不是0/1背包。从大到小遍历可以保证在更新dp[j]时dp[j - w_i]还是上一轮的值。def knapsack_1d(weight, value, capacity): n len(weight) # 初始化一维dp数组dp[j]表示容量为j的背包能装的最大价值 dp [0] * (capacity 1) # 遍历每一件物品 for i in range(n): w_i, v_i weight[i], value[i] # 关键内层循环从大到小遍历容量 for j in range(capacity, w_i - 1, -1): dp[j] max(dp[j], dp[j - w_i] v_i) # 上面的代码等价于 # if j w_i: # dp[j] max(dp[j], dp[j - w_i] v_i) # 因为循环范围已经是 j w_i所以可以直接计算 return dp[capacity] # 测试 print(knapsack_1d(weight, value, capacity)) # 同样输出 10这个一维DP版本是面试和刷题中最常见的写法空间复杂度优化到了O(W)。务必理解并记住“逆序更新”这个关键点这是0/1背包的核心代码模板。实操心得一维DP的写法简洁高效但可读性稍差且丢失了具体物品选择方案的信息。在初次学习或调试时我建议先用二维DP写出来确保逻辑正确再优化成一维。这能帮你建立更扎实的理解。5. 问题变形与实战应用掌握了标准的0/1背包模型我们就可以解决一大票变形问题了。它们的本质都是“在某种限制容量下对一组物品进行选择选或不选以优化某个目标最大/最小值”。5.1 恰好装满 vs 不超过容量我们之前讨论过这两种初始化方式。总结一下要求恰好装满dp[0][0]0其他dp[0][j] -inf或一个非常小的负数。最终dp[n][capacity]就是答案。如果结果是负数说明无法恰好装满。要求不超过容量dp[0][j] 0。最终dp[n][capacity]是答案。这种方法更常用。在一维DP中“恰好装满”的初始化变为dp[0]0,dp[1..capacity]-inf。5.2 求方案数比如“目标和”问题问题给定一个非负整数数组nums和一个目标数S给每个数前面添加或-使得表达式结果等于S求有多少种添加符号的方法。 这可以转化为背包问题设所有带的数之和为P带-的数之和为N则有P - N S且P N sum(nums)。解方程得P (S sum) / 2。问题就变成了从nums中选若干个数使它们的和恰好为(S sum) / 2有多少种选法这就是一个“恰好装满”的背包问题但dp[j]的含义从“最大价值”变成了“方案数”。状态转移dp[j] dp[j - nums[i]]。初始化dp[0] 1凑出和为0的方案有一种什么都不选其他为0。5.3 求最小物品数比如“硬币找零”的硬币最少版本问题给定不同面额的硬币coins和一个总金额amount计算可以凑成总金额所需的最少的硬币个数。 这可以看作背包容量为amount每个物品硬币的重量是coins[i]价值是1代表硬币个数。我们要找的是“恰好装满”背包时的“最小价值”。状态转移dp[j] min(dp[j], dp[j - coins[i]] 1)。初始化dp[0]0,dp[1..amount]inf一个大数。5.4 二维费用背包问题物品不仅有重量weight还有体积volume背包有重量限制W和体积限制V。这就是二维费用背包。 解决方案很简单将状态数组升到三维dp[i][j][k]或者用优化后的二维滚动数组dp[j][k]。状态转移方程类似dp[j][k] max(dp[j][k], dp[j-w_i][k-v_i] value[i])。遍历顺序则需要两层逆序循环。6. 常见陷阱与调试技巧即使理解了原理自己写代码时还是会踩坑。下面是我总结的几个常见问题和解决方法。6.1 遍历顺序错误这是最经典的错误尤其在一维DP中。错误内层循环对容量j进行从小到大遍历。这会导致物品被重复计算变成了“完全背包”的解法。正确内层循环对容量j必须从大到小遍历。6.2 索引混淆在二维DP中物品下标i从1开始对应物品属性时要减1 (weight[i-1])。在一维DP中物品下标i从0开始直接对应 (weight[i])。混合使用会导致数组越界或逻辑错误。调试技巧在循环开始打印i,w_i,v_i的值确认你取到的物品信息是正确的。6.3 初始化问题“恰好装满”问题忘记初始化-inf这会导致程序将“装不满”的状态也当作合法状态参与转移得出错误的最大值。例如用全0初始化去解“恰好装满”问题程序可能会用一个“装不满”但价值更高的假状态来更新dp[j]。“求最小值”问题忘记初始化inf同理如果用0初始化min(dp[j], dp[j - w] 1)的结果永远会是0。6.4 状态转移方程的条件判断遗漏在一维DP的逆序循环中我们通常把循环范围写成for j in range(capacity, w_i - 1, -1)这样保证了j w_i可以直接进行max比较。如果你写的是for j in range(capacity, -1, -1)那么在循环体内就必须加上if j w_i:的判断否则会访问dp[j - w_i]的负索引。6.5 如何输出具体选择了哪些物品标准的DP只给出了最大价值要回溯找到具体方案需要额外的记录。 在二维DP中我们可以从最终状态dp[n][capacity]开始倒推如果dp[i][j] dp[i-1][j]说明第i件物品没被选。如果dp[i][j] dp[i-1][j - weight[i-1]] value[i-1]说明第i件物品被选了然后我们跳到状态dp[i-1][j - weight[i-1]]继续判断。 这种方法需要完整的二维DP表。一维DP由于覆盖了历史信息无法直接回溯。如果题目要求输出方案通常就得使用二维DP。最后学习动态规划和背包问题没有捷径最好的方法就是“动手”。找几道经典的力扣题目如416. 分割等和子集、494. 目标和、474. 一和零先用我们这里讲的思路去分析识别出它是不是背包问题容量是什么物品是什么价值是什么然后自己动手实现。遇到问题就回来看看状态定义和转移方程或者画一个小的表格手动模拟一下过程。这个过程可能会重复很多次但每重复一次你的理解就会加深一层。当你不再害怕状态转移方程能够自如地将各种问题映射到背包模型时你就真正掌握了这把算法利器。

相关新闻

数据库设计实战:从E-R图到关系表的完整指南与避坑策略

数据库设计实战:从E-R图到关系表的完整指南与避坑策略

1. 项目概述:从概念到实现的桥梁如果你刚接触数据库设计,可能会觉得一堆“实体”、“关系”这些词有点抽象,但别担心,这其实就是把现实世界里的东西和它们之间的联系,用一种计算机能懂的方式画出来、写下来的过程。E-R…

2026/8/11 5:20:49 阅读更多 →
Django连接MySQL全攻略:跨平台环境配置与避坑指南

Django连接MySQL全攻略:跨平台环境配置与避坑指南

1. 项目概述与核心价值 搞Python Web开发,Django绝对是绕不开的框架,而数据库选型里,MySQL又是最经典、应用最广的关系型数据库之一。把这两者顺畅地连接起来,是每个Django开发者入门后要跨过的第一道“实战坎”。这个项目标题“…

2026/8/11 5:19:49 阅读更多 →
Unity插件选型与实战指南:50款热门工具提升开发效率

Unity插件选型与实战指南:50款热门工具提升开发效率

1. 项目概述:为什么你需要一份Unity插件“藏宝图”?做Unity开发这些年,我最大的感受就是:一个项目能不能高效、高质量地完成,很多时候不取决于你写了多少行代码,而在于你是否知道并善用那些“神器”级别的插…

2026/8/11 5:19:49 阅读更多 →

最新新闻

鸿蒙音视频播放之HLS拉流播放实现

鸿蒙音视频播放之HLS拉流播放实现

HLS 流媒体简介 HLS全称为HTTP Live Streaming,是苹果推出的基于HTTP的流媒体传输协议。该协议会把完整的流媒体文件拆分为多个TS格式的小分片文件,同时生成M3U8索引播放列表。客户端按照顺序下载各个分片文件,完成流媒体的播放。 HLS最主要的特性是支持自适应码率ABR,可根…

2026/8/11 6:00:01 阅读更多 →
Claude Code记忆系统深度解析:AI编程助手的长期记忆机制与应用实践

Claude Code记忆系统深度解析:AI编程助手的长期记忆机制与应用实践

1. 项目概述:从“浅尝”到“深挖”的探索最近在折腾AI编程助手时,我花了些时间专门研究了一下Claude Code的“记忆系统”。这玩意儿听起来挺玄乎,但说白了,就是AI在跟你一起写代码时,能记住之前聊过的上下文、你提过的…

2026/8/11 6:00:01 阅读更多 →
CBCX:投教内容背后的视角与观察重点

CBCX:投教内容背后的视角与观察重点

在外汇相关服务里,CBCX是否值得长期关注,往往取决于几个清晰的体验点:说明是否好理解、提示是否到位、流程是否连贯、支持是否稳定。下面从这些维度对CBCX做一次正向梳理与要点归纳。外汇相关信息更新频繁,平台将关键提示与解释呈…

2026/8/11 6:00:01 阅读更多 →
GitHub Copilot 子 Agent 并行改仓:合并冲突吃掉 3 天——我的分支锁文件止血方案

GitHub Copilot 子 Agent 并行改仓:合并冲突吃掉 3 天——我的分支锁文件止血方案

GitHub Copilot 子 Agent 并行改仓:合并冲突吃掉 3 天--我的分支锁文件止血方案 GitHub Copilot 多 Agent 并行开发的冲突治理实战 问题爆发:当 AI 协作变成灾难 灰度上线的第 2 天,我的企业微信突然被 爆了--5 个并行改仓的 GitHub Copilot 子 Agent 同时提交了代码,结果合…

2026/8/11 6:00:01 阅读更多 →
十万卡国产超集群落地,引爆行业重构:2026 中国服务器市场深度分析

十万卡国产超集群落地,引爆行业重构:2026 中国服务器市场深度分析

一、整体大盘行情:总量稳步增长,结构彻底分化1. 市场规模:AI 服务器扛起行业增长大旗2026 年全球服务器整体市场保持较高景气度,一季度全球服务器厂商整体收入 1226 亿美元,同比上涨 30.4%,增长主要由 AI 算…

2026/8/11 6:00:01 阅读更多 →
B站弹幕二进制协议逆向解析:从Protobuf到Frida Hook实战

B站弹幕二进制协议逆向解析:从Protobuf到Frida Hook实战

1. 项目概述:从B站弹幕到二进制解析的探索最近在做一个跟B站视频数据相关的项目,不可避免地要跟它的弹幕系统打交道。我们都知道,B站的弹幕是它的灵魂,但当你真正想从技术层面去“理解”这些弹幕时,会发现它们并非以我…

2026/8/11 5:59:00 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →