我有一个固定的权重列表:
int[] weights = new int[] { 10, 15, 20 };
和目标:
int target = 28;
我正在寻找一种算法,将target
表示为来自weights
的元素总和(允许重复),以使target
匹配或超过,实现与target
最接近的匹配,并且在此范围内,使用的数量最小化。
因此,通过上述输入,我希望返回10 20
或15 15
,因为30
尽可能接近,以及制作{{1}的选项这两个比30
好。
如果10 10 10
为target
,则输出应为39
,而不是20 20
或15 15 10
。
如果10 10 10 10
为target
,则输出应为14
。
除了常规的foreach循环之外,这里有一个好的方法吗?我正在考虑检索数组中可用的最大值并检查目标是否为负数,如果没有,那么让我们去寻找下一个值。
这不是作业:)
答案 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
测试体重123