将整数表示为一些其他固定整数的总和

时间:2012-07-10 08:25:16

标签: c# .net algorithm

我有一个固定的权重列表:

int[] weights = new int[] { 10, 15, 20 };

和目标:

int target = 28;

我正在寻找一种算法,将target表示为来自weights的元素总和(允许重复),以使target匹配或超过,实现与target最接近的匹配,并且在此范围内,使用的数量最小化。

因此,通过上述输入,我希望返回10 2015 15,因为30尽可能接近,以及制作{{1}的选项这两个比30好。

如果10 10 10target,则输出应为39,而不是20 2015 15 10

如果10 10 10 10target,则输出应为14

除了常规的foreach循环之外,这里有一个好的方法吗?我正在考虑检索数组中可用的最大值并检查目标是否为负数,如果没有,那么让我们去寻找下一个值。

这不是作业:)

2 个答案:

答案 0 :(得分:3)

这被称为knapsack problem。唯一的区别是您正在寻找最近的匹配,而不是最接近的匹配。幸运的是,没有一个权重具有不同的值。困难在于您不能简单地使用最接近的weights之一并使用剩余值进行递归(较小值的组合有时会更好地匹配)。

在你的例子中,weights之间都有5个“单位”,如果总是如此,那么问题将变得更容易解决。

答案 1 :(得分:2)

我已经设法找到了一个解决方案,感谢大家在这里让我更清楚我实际需要什么。这不是我编写的最漂亮的代码,但无论如何这都是MVP开发!

private static List<int> WeightsJuggle(List<int> packages, IOrderedEnumerable<int> weights, int weight)
{
    if (weight == 0)
        return packages;

    foreach (int i in weights.Where(i => i >= weight))
    {
        packages.Add(i);
        return packages;
    }

    packages.Add(weights.Max());
    return WeightsJuggle(packages, weights, weight - weights.Max());
}

我称之为

IOrderedEnumerable<int> weights = new int[] { 10, 15, 20 }.OrderBy(x => x);
int weight = 65;
List<int> packages = new List<int>();

测试体重65

enter image description here

测试体重123

enter image description here