对于给定的一组数字{12,13,15,21,22,26,6,14,27,28,29,30,39,40,4,17,25}
,我想找到满足这两个条件的最小子集数。
5
。(num1-num2)% d != 0
。 num1>num2
和其中d是常数差异
两个数字之间。对于上面的示例:如果d=4
和子集中的元素数量为5
,那么其中一个子集将为:{12,13,15,22,17}
我正在寻找一种算法来查找满足条件的最小子集数。
答案 0 :(得分:0)
好的,所以它不是100%关于编程。这是一项标准的离散数学练习。
让我们分步进行:
答案 1 :(得分:0)
你可以贪婪地解决这个问题。
将你的集合划分为S [i],其中S [i] = {s在S中,s%d == i}。
然后,重复选择k(在您的示例中为5)最大子集S [i]并从每个子集中删除一个元素。
这里有一些效率稍低但很简单的代码可以实现这个目的:
def part(S, k, d):
"Split S into subsets of size<=d, each with elements unique mod k"
parts = [[] for _ in xrange(k)]
for s in S:
parts[s % k].append(s)
while sum(len(p) for p in parts):
parts.sort(key=len, reverse=True)
yield [x.pop() for x in parts[:d] if x]
S = [12,13,15,21,22,26,6,14,27,28,29,30,39,40,4,17,25]
for s in part(S, 6, 5):
print sorted(s)
此代码的输出,显示大小最多为5的子集,使得没有子集包含两个等于模6的数字:
[4, 14, 25, 30, 39]
[6, 13, 17, 27, 40]
[12, 21, 26, 28, 29]
[15, 22]
可以使用优先级队列和正在运行的计数器优化parts
和while循环条件,但这会模糊正在发生的事情。优化后的表格将在O(n log n)时间内运行;写成它的O(n ^ 2 log n)
[我应该说,我很确定这个解决方案是正确的,但我不太清楚如何证明这一点。我有兴趣看一个证明(或一个反例来证明它是错的)。]
答案 2 :(得分:0)
我会做这样的事情:
def run(self, n,m):
if len(n)<=1:
return [n]
x = n[0:1] //get 1st part
y = n[1:] //get remaining
t = self.run(y,m)
r=[]
if t:
r+=[x] //add current element
r+=[i for i in t if count(i)<=m] // add fixed combinations
r+=[ i+x for i in t if valid(i+x)] // all combined combinations
return r
def valid(combination):
//code to check your condition
(num1-num2)% d != 0