
1) 【一句话结论】:该问题可转化为0-1背包问题,通过动态规划求覆盖所有知识点的最少题目数,状态定义基于知识点覆盖集合,状态转移考虑题目选择与否,时间复杂度O(n * m),空间复杂度O(2^n)(知识点数n)。
2) 【原理/概念讲解】:动态规划的核心是子问题分解与重叠子问题。这里知识点集合为S,题目集合为P,每个题目p有覆盖的知识点集合C(p)和成本c(p)。目标是找到最小成本的题目集合,使得∪C(p) = S。类比0-1背包:知识点是“物品”(需要选的集合),题目是“背包”(每个背包有容量(覆盖的知识点)和重量(成本),且每个物品最多选1次)。状态定义用位掩码表示已覆盖的知识点集合,dp[mask]表示覆盖mask所需的最少题目数,状态转移为遍历所有题目,若题目覆盖的知识点在mask中,则更新新状态。关键在于用位运算高效表示知识点集合,避免暴力枚举所有子集。
3) 【对比与适用场景】:
| 模型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 0-1背包(本题) | 每个题目(物品)只能选或不选,知识点(容量)需覆盖 | 每个物品最多选1次,状态转移需考虑所有子集 | 知识点覆盖、资源有限且不可分割的优化问题 | 状态转移需遍历所有可能的状态,位掩码优化状态表示 |
| 完全背包 | 每个题目可重复选 | 状态转移中需考虑当前物品的重复选择 | 题目可重复使用,如购买物品 | 需调整循环顺序(外层循环物品,内层循环状态) |
4) 【示例】:知识点数n=3(知识点1,2,3),题目数m=2。题目1:覆盖{1,2},成本1;题目2:覆盖{2,3},成本1。状态定义dp[mask]表示覆盖mask(二进制,如001=知识点2被覆盖)的最少题目数。初始化dp[0]=0,其他为INF。遍历题目1:对于mask从7到0,若mask包含1或2(即mask & (1<<1) || mask & (1<<2)),则new_mask = mask | (1<<1 | 1<<2),更新dp[new_mask]为min(dp[new_mask], dp[mask]+1)。遍历题目2:同理。最终dp[7](111,所有知识点覆盖)的值为2(题目1和题目2),即最少2个题目覆盖所有知识点。
5) 【面试口播版答案】:各位面试官好,这个问题属于动态规划中的0-1背包变种。核心思路是将知识点看作需要覆盖的“物品”,题目看作“背包”,每个题目只能选或不选(0-1)。状态定义用位掩码表示已覆盖的知识点集合,dp[mask]表示覆盖mask所需的最少题目数。状态转移方程是:对于每个题目i,遍历所有当前状态mask,若题目i覆盖的知识点在mask中,则更新新状态为mask | 题目i的覆盖掩码,并更新dp[new_mask]为min(dp[new_mask], dp[mask] + 1)。边界条件是dp[0]=0(覆盖空集需要0个题目),其他为无穷大。复杂度分析:知识点数n,题目数m,状态数2^n,每个状态遍历m个题目,时间复杂度O(n * 2^n),空间复杂度O(2^n)。最终结果是dp[(1<<n)-1],若为无穷大则无解。这样就能得到覆盖所有知识点的最少题目数。
6) 【追问清单】:
7) 【常见坑/雷区】: