将一组数字的元素求和为给定数字

时间:2018-08-17 02:14:20

标签: algorithm

我一直在努力提出一种算法来解决这个问题。 假设我有一组数字{1, 2, 5},并且该集合中的每个元素都是无限制供应,而我给了另一个数字6,然后要求确定可以对元素求和以获得数字6的方式数量。出于说明目的,我这样做

1 + 1 + 1 + 1 + 1 + 1 = 6

1 + 1 + 2 + 2 = 6

2 + 2 + 2 = 6

1 + 5 = 6

1 + 1 + 1 + 1 + 2 = 6

因此,在这种情况下,程序将输出5作为路数。再次让您说要找到4的总和。

1 + 1 + 1 + 1 = 4

2 + 2 = 4

1 + 1 + 2 = 4

在这种情况下,算法将输出3作为路数

3 个答案:

答案 0 :(得分:4)

这类似于子集总和问题。我确定您必须使用分支定界方法或回溯方法。

1)创建一个状态空间树,其中包含所有可能的情况。

                        0
                    /   |   \
                   1    2     5
                 / | \
                1  2  5 ........

2)继续该过程,直到深度优先的节点总数大于或等于您想要的数量为止。

3)计算编号满足您条件的完整分支。

类似问题的python实现可以在here中找到。

答案 1 :(得分:3)

使用recursiondynamic programming技术是一个好问题。这是使用自顶向下方法(memoization)的Python实现,以避免多次进行相同的计算:

# Remember answers for subsets
cache = {}

# Return the ways to get the desired sum from combinations of the given numbers
def possible_sums(numbers, desired_sum):
  # See if we have already calculated this possibility
  key = (tuple(set(numbers)), desired_sum)
  if key in cache:
    return cache[key]

  answers = {}
  for n in numbers:
    if desired_sum % n == 0:
      # The sum is a multiple of the number
      answers[tuple([n] * (desired_sum / n))] = True

    if n < desired_sum:
      for a in possible_sums(numbers, desired_sum - n):
        answers[tuple([n] + a)] = True

  cache[key] = [list(k) for k in answers.iterkeys()]
  return cache[key]

# Return only distinct combinations of sums, ignoring order
def unique_possible_sums(numbers, desired_sum):
  answers = {}
  for s in possible_sums(numbers, desired_sum):
    answers[tuple(sorted(s))] = True
  return [list(k) for k in answers.iterkeys()]

for s in unique_possible_sums([1, 2, 5], 6):
  print '6: ' + repr(s)

for s in unique_possible_sums([1, 2, 5], 4):
  print '4: ' + repr(s)

答案 2 :(得分:1)

对于较小的目标数量(〜1000000)和1000 {supply} n,请尝试以下操作:

提供您的号码

supply {a,b,c....}

您需要的目标

steps[n]

1种获得0的方式什么都不用

steps[0]=1

扫描到目标号码

for i from 1 to n:
  for each supply x:
if i - x >=0 
     steps[i] += steps[i-x]

第n步将包含路数

steps[n]

以上内容的可视化:     供应{1、2、5},目标6

i = 1, x=1 and steps required is 1
i = 2, x=1 and steps required is 1
i = 2, x=2 and steps required is 2
i = 3, x=1 and steps required is 2
i = 3, x=2 and steps required is 3
i = 4, x=1 and steps required is 3
i = 4, x=2 and steps required is 5
i = 5, x=1 and steps required is 5
i = 5, x=2 and steps required is 8
i = 5, x=5 and steps required is 9
i = 6, x=1 and steps required is 9
i = 6, x=2 and steps required is 14
i = 6, x=5 and steps required is 15

一些Java代码

   private int test(int targetSize, int supply[]){
        int target[] = new int[targetSize+1];
        target[0]=1;
        for(int i=0;i<=targetSize;i++){
            for(int x:supply){
                if(i-x >= 0){
                    target[i]+=target[i-x];
                }
            }
        }
        return target[targetSize];
    }

    @Test
    public void test(){
      System.err.println(test(12, new int[]{1,2,3,4,5,6}));
    }