如何找到最接近另一个数字的2个数字的最小组合

时间:2018-02-14 06:37:52

标签: algorithm math

我有两个数字:6& 10

我想使用这两个数字的组合来尽可能接近另一个数字。

例如,要达到9,我需要1 6,其余3。 其他例子:

6: [6]
10: [10]
12: [6, 6]
18: [6, 6, 6]
20: [10, 10]
24: [6, 6, 6, 6]
26: [10, 10, 6]
28: [10, 6, 6, 6]
30: [10, 10, 10]
32: [10, 10, 6, 6]

我需要一种能够找到任意给定数量的最小组合数的算法,优先选择具有最小余数的组合。即

38: [10, 10, 10, 6] - 2 remaining
38: [10, 10, 6, 6, 6] - no remainder, so preferred result

我希望我已经清楚地解释了这一点,如果我需要澄清,请告诉我。

更新: 澄清一下,这是处理实物的现实问题。数字6&图10对应于包含6或10个量的产品的倍数的包装箱。我们接受任何数量的这些产品的订单,并且想要计算可以组成订单的最小数量的纸箱,然后将剩余部分添加为单独的qtys。

客户可能需要订购39的数量,因此我需要知道最少数量的6/10数量的纸箱来组成订单,剩余的最小数量是优先权。

客户也可以订购1,2,3,4,5,6 .....的qtys,最多约300个。

4 个答案:

答案 0 :(得分:0)

考虑到你想要在a和b的因子中对n进行因子分解,那么你只需要将两种可能的方法分解,并检查哪一种方法给你最小的余数。

所以,你可以这样:

def factorize(a, b, n):
   return n/a, (n%a)/b, (n%a)%b

def factorize_min(a, b, n):
   na1, nb1, r1 = factorize(a, b, n)
   nb2, na2, r2 = factorize(b, a, n)
   return (na1, nb1) if r1 < r2 else (na2, nb2)

def factorize_min_list(a, b, n):
   na, nb = factorize_min(a, b, n)
   return [a]*na + [b]*nb

并像这样使用它:

for n in (6,10,12,18,20,24,26,28,30,32):
    print factorize_min_list(6, 10, n)

这会给你:

[6]
[10]
[6, 6]
[6, 6, 6]
[10, 10]
[6, 6, 6, 6]
[6, 10, 10]
[6, 10, 10]
[10, 10, 10]
[10, 10, 10]

答案 1 :(得分:0)

这种change-making problem可以通过动态编程有效地解决。请注意,如果需要sum,则无法精确生成(如示例中的9) - 检查DP表的下邻居单元格。

答案 2 :(得分:0)

这或多或少是硬币问题。在Frobenius数字之上,可以构建所有值。这里我们有6个和10个不是互质的。因此,我们可以除以最大公约数(2)得到3和5这是互质的。然后我们得到Frobenius数3 * 5 - 5 - 3 = 7.这意味着所有偶数值&gt; 14可以使用6和10个硬币建造。价值很少,你可以只列出一个清单:

  1. 3(%3 = 0),硬币(1,0)
  2. 5(%3 = 2),硬币(0,1)
  3. 6(%3 = 0),硬币(2,0)
  4. 8(%3 = 2),硬币(1,1)
  5. 9(%3 = 0),硬币(3,0)
  6. 10(%3 = 1),硬币(0,2)
  7. 所以算法如下:

    1. 将输入除以2
    2. 如果小于11,则返回列表中最接近的6个值
    3. 否则输入%3,采取相应的配置(8,9或10),从输入中减去它,除以3并将结果加到3(即6)硬币
    4. 32(或33)的例子:

      1. 32/2 = 16
      2. 16&gt; = 11
      3. 16%3 = 1,我们取10(0,2),(16 - 10)/ 3 = 2,将其加到3个硬币=&gt; (2,2)
      4. 检查:2 * 6 + 2 * 10 = 32

答案 3 :(得分:0)

以下是使用动态编程解决问题的C版本。 编译之后,您可以使用项目总数作为参数运行它 它将输出由标签分隔的包装尺寸10和6 然后是他们的总和。 我从德国维基百科页面上获取了关于背包问题的算法 data url

在开头的评论中引用:

/*
U = { 10, 6 } n = 2
w = { 10, 6 }
v = {  2, 1 }

Eingabe: U, B, w, v wie oben beschrieben
  R := [1…(n+1), 0…B]-Matrix, mit Einträgen 0
  FOR i = n … 1
    FOR j = 1 … B
      IF w(i) <= j
        R[i,j] := max( v(i) + R[i+1, j-w(i)], R[i+1,j]\
 )
      ELSE
        R[i,j] := R[i+1,j]
Ausgabe: R[1,B]
*/
#include <stdlib.h>
#include <stdio.h>

int n = 2;
int main(int argc, char** argv) {
  int w[3] = { -1, 10, 6 };
  int v[3] = { -1, 10, 6 };
  int B = atoi(argv[1]);
  size_t sz = ((B+1)*3*sizeof(int));
  int* R = malloc(sz);
  memset(R, 0, sz);
  for(int i = n; i > 0; i--) {
    for(int j = 1; j <= B; j++) {
      int b = R[i+1,j];
      if(w[i] <= j) {
        // max( v(i) + R[i+1, j-w(i)], R[i+1,j] )
        int a = v[i] + R[i+1, j-w[i]];
        R[i,j] = a>b?a:b;
      } else {
        R[i,j] = b;
      }
    }
  }
  int k = R[1,B];
  while(R[1,k]>0){
    int j = R[1,k];;
    for(int i = n; i > 0; i--) {
      int t = R[1,k-w[i]];
      if(t == k - w[i]) {
        j = w[i];
      }
    }
    printf("%i\t",j);
    k = k-j;
  }
  printf("\n%i\n", R[1,B]);

  return 0;
}