我有两套,比如A = {0,1,2,...,i}和B = {3,6,10,15},一个常数$ s $和一个指定数字$ n $属于自然数集。 我想找到满足a_1 * b_1 + a_2 * b_2 + \ dots + a_n * b_n> = s
的/所有组合例如,如果s = 25,则n = 2以下每个答案都是可接受的1 * 10 + 1 * 15,2 * 10 + 1 * 6,0 + 2 * 15或4 * 3 + 2 * 6 < / p>
如果我没有第二组,那么这很容易,因为问题会减少到产生here中引入的预定和的随机分区
我应该如何在python中有效地实现它?有什么数学方法吗? 它也让我想起某种方程式,但我不确定我应该搜索什么。 我很欣赏任何提示。
编辑:对我而言,确切地说&#34; n&#34;在我的答案中的条款,并有机会其他选择。在我的例子中,四个答案中的每一个都应该有生成的机会。换句话说,我有&#34; n&#34;用他们的条款填写他们的总和等于&#34; s&#34;。抱歉不要在第一时间清除它。
答案 0 :(得分:2)
可以通过直接递归来完成。
from functools import lru_cache
def find_combinations(numbers, threshold, nterms, maxcoeff, stringify=True):
numbers = sorted(numbers, reverse=True)
@lru_cache(None)
def rec(k, s, n):
if s > maxcoeff * numbers[k]:
top = maxcoeff
res = []
else:
top = (s-1) // numbers[k]
res = [[top + 1]]
if n > 1 and k < len(numbers)-1:
for j in range(top, -1, -1):
res.extend([[j, *subres] for subres in rec(
k+1, s-j*numbers[k], n-(j!=0))])
return res
if stringify:
return [' + '.join(f'{c}\u2a2f{n}' for c, n in zip(sol, numbers) if c)
for sol in rec(0, threshold, nterms)]
else:
return rec(0, threshold, nterms)
print(find_combinations({3, 6, 10, 15}, 25, 2, 2))
打印:
['2⨯15', '1⨯15 + 1⨯10', '2⨯10 + 1⨯6']
更新:允许numbers
多次出现(这些被混为一谈,基本上maxcoeff乘以每个数字的出现次数):
def find_combinations_with_replacement(numbers, threshold, nterms, maxcoeff,
stringify=True):
numbers = sorted(numbers, reverse=True)
@lru_cache(None)
def rec(k, s, n):
if s > maxcoeff * numbers[k] * n:
return []
top = (s-1) // numbers[k]
res = [[top + 1]]
if n > 1 and k < len(numbers)-1:
for j in range(top, -1, -1):
res.extend([[j, *subres] for subres in rec(
k+1, s-j*numbers[k], n - (j-1) // maxcoeff - 1)])
return res
if stringify:
return [' + '.join(f'{c}\u2a2f{n}' for c, n in zip(sol, numbers) if c)
for sol in rec(0, threshold, nterms)]
else:
return rec(0, threshold, nterms)
print(find_combinations_with_replacement({3, 6, 10, 15}, 25, 4, 1))
打印:
['2⨯15', '1⨯15 + 1⨯10', '1⨯15 + 2⨯6', '1⨯15 + 1⨯6 + 2⨯3', '3⨯10', '2⨯10 + 1⨯6', '2⨯10 + 2⨯3', '1⨯10 + 3⨯6', '1⨯10 + 2⨯6 + 1⨯3']