如何找到列和至少达标的最小基数行子集,求对应高效算法
多维最小覆盖问题解决方案
问题定性
你描述的问题属于经典的多维最小覆盖问题,是NP难问题,目前没有通用的多项式时间精确最优解法,可根据数据规模选择对应的方案:
1. 小规模场景(求精确最优解)
如果S的元素总数≤20,或者数组维度n≤15,可以用以下两种方案:
- 状态压缩动态规划
定义dp[mask]为选择mask二进制位对应子集时,各维度的求和结果。遍历所有mask,每次加入一个未选中的数组更新状态,一旦某个状态的所有维度值都≥T对应值,此时mask中1的个数就是最小基数,可直接返回。 - 整数规划建模
直接用整数规划框架求解,建模逻辑如下:决策变量:
x_j ∈ {0,1}表示是否选中S中的第j个数组
优化目标:最小化所有x_j的和
约束条件:对每一个维度i,所有x_j * 第j个数组的第i位之和 ≥ T的第i位
调用pulp、ortools等开源整数规划工具即可快速得到精确解。
2. 大规模场景(求近似最优解)
如果数据量很大无法做暴力枚举,可以用贪心算法快速得到接近最优的结果,近似比为O(log n),绝大多数实际场景下效果足够:
- 初始状态各维度求和为0,计算每个维度的缺口 = max(0, T[i] - 当前和[i])
- 每一轮遍历剩余未选的数组,计算每个数组的收益:所有缺口>0的维度中,该数组对应位的数值之和(也可根据业务调整收益规则,比如优先覆盖缺口最大的维度)
- 选中收益最高的数组加入结果集,更新各维度当前和与缺口
- 重复步骤2-3直到所有维度缺口都为0
示例验证
你的示例输入:
T = [2, 3, 1] S = [[0, 1, 2], [1, 0, 1], [2, 2, 0]]
初始缺口为[2, 3, 1]:
- 第一轮计算三个数组收益分别为3、2、4,选中第三个数组,更新当前和为
[2, 2, 0],缺口变为[0, 1, 1] - 第二轮计算剩余两个数组收益分别为3、1,选中第一个数组,更新当前和为
[2, 3, 2],所有缺口清零
最终得到的子集大小为2,和最优解一致。
内容的提问来源于stack exchange,提问作者nb550
相关产品推荐
相关产品推荐

