找到使用加数组合的最佳方法,以获得具有有限数量的加数的最大总和

时间:2012-10-21 01:04:26

标签: algorithm math computer-science theory combinations

我有点问题,我有一组加起来为X的总和,如下:

A:i + j + k = X

B:t + z = X

C:z + z = X

D:j + j + k + k = X

这些总和可以或多或少,我在这里给4但可能有N个。

我的请求数量有限,例如我有

12 i,z 35,j 12,k 18,t 21

我需要的是一种算法,它将决定使用这些组合的最佳方式,以便最终获得最完整的X总和

所以在上面的例子中使用:

组合C中的17个,组合B中的1个和组合A中的12个,总共30个X,72个使用的总和

更糟糕的是使用:

组合B中的21个,组合C中的7个和组合D中的6个,总共34个X的总和,80个使用的加数

编辑:

进一步解释

使用组合B中的21将“花费”21 t和21 z离开我们:i的12,z的14,j的12,k的18,0的t

使用组合C中的7将“消耗”z的14(因为它使用了2个z的要求),给我们留下:12的i,0的z,12的j,18的k,0的t

使用6个组合D将花费12个j和12个k(因为它使用它们两个)留下我们:12个i,0个z,0个j,6个k,0个t < / p>

我们不能再制作能够加起来X的组合,从而得出算法。

1 个答案:

答案 0 :(得分:1)

我写了一个程序来强行解决这个问题。

对于您的示例数据,哪种最佳组合给出了:

  组合A中的1个,组合B中的19个和组合C中的7个,5个   组合D,总共32个X的和,75个使用的加数

代码虽然不是那么整洁,但可能不正确:

# Consider encoding the states
#{i,j,k}
#{i,z}
#{z,z}
#{j,j,k,k}
#as
#          i   z   j   k
limits =  (21, 35, 12, 18)
sets   = [(1,0,1,1), #
          (1,1,0,0), #
          (0,2,0,0), #
          (0,0,2,2), #
          ]

from heapq import heappush, heappop

def sub(A,B): return tuple(x - y for x,y in zip(A,B))

H = [(0,limits,[0]*len(sets))]
B = []
#X = 0
while H:
    #X += 1
    C, available, counts = heappop(H)
    #if X%1000 == 0: 
    #print C, available, counts
    if not any(all(not x > 0 for x in sub(available, s)) for s in sets):
        E = -C, sum(available), available, counts
        if E not in B:
            #print "found:", E
            if len(B) > 0:
                #print "best:", B[0]
                pass
            heappush(B, E)
    for i,s in enumerate(sets):
        diff = sub(available, s)
        if all(x > 0 for x in diff):
            counts_ = counts[:]
            counts_[i] += 1
            E = (C+1, diff, counts_)
            if E not in H:
                heappush(H, E)

a,b,c,d = heappop(B)

print "%u of combination A, %u of combination B, and %u of combination C, %u of combination D, total %u sums of X, %u summands used" % tuple(d+[-a, sum(limits)-sum(c)])

编辑:

将修改过的问题输入此程序后,它会在9秒内生成:

  组合A中的11个,组合B中的20个和组合C中的7个,0个   组合D,总共38个X的和,87个使用的加数

修订问题的编码:

#         i  z  j  k  t
limits = (12,35,12,18,21)
sets   = [(1,0,1,1,0), # {i,j,k}
          (0,1,0,0,1), # {t,z}
          (0,2,0,0,0), # {z,z}
          (0,0,2,2,0), # {j,j,k,k}
          ]