我正在编写一个程序,我需要对作业进行分组,以最大限度地减少CNC打孔的工具更改。我刚开始的时候问了一个关于它的问题,但是当我编写程序时,方法已经改变了。
我有一份工作清单:
jobs = ['5618', '5612', '5613', '5897', '5589', '5474',
'5472', '5470', '5471', '9040']
我的程序已经将这些分类为可以一起完成的有效“工作组”:
['5471', '9040']
['5618', '5612', '5613', '5472']
['5471', '5589', '5897']
['5618', '5612', '5471', '5613']
['5471', '5474']
['5471', '5470', '5589']
现在我需要选择意味着完成所有工作的最小组数。 猜测是这个组合:
['5618', '5612', '5613', '5472']
['5471', '5589', '5897']
['5470', '5589'] #this is the last group in the above lists but with 5471
#removed because it's already been done
[9040] #same as above except the first group with 5471 already been done.
我在逻辑上考虑这样做的方法是找到最长的有效组,假设是第一组,从剩余的作业中删除该组中的作业。重复。 但是,当有两个具有相同长度的组时,这不起作用。也许根据工作在其他群体或其他事物中的次数来加权?我不知道。想法? 蛮力吗?哈哈
答案 0 :(得分:6)
此问题称为set cover problem。从本质上讲,您要求的是最小的一组组,这些组将涵盖您想要完成的所有工作。
不幸的是,问题是NP完全。因此,找到解决方案的可能性不大。但是,如果你有少量的工作或小组(因为你可以蛮力),这可能无关紧要。
你提出的贪婪算法实际上非常好,相当于链接的维基百科页面上的贪婪算法。它实际上是仍然在多项式时间内运行的“最佳”算法。要打破关系,任意选择(事实证明并不重要)。
如果工具更改的费用足以保证额外的CPU时间,则可以通过考虑所有2 ^ n个可能的组(其中n是组的数量)来强制解决问题。您可以轻松地使用典型机器处理n = 20,如果您愿意等待一段时间,最多可以处理n = 30。您可以对强力实施优化,以减少它将检查的解决方案的数量(特别是,您可以在设置图中进行广度优先搜索,以便在找到第一个最小解决方案时停止),但同样您仍将结束做一个指数的工作来找到真正的最佳解决方案。