已知一个集合 int[] data = new int[]{100,50,30,20,10,5};要求 从这里面取数字,允许重复,在不超过指定个数下,算出最小的和为指定值或比指定值大但最接近的列表,相等优先,最小值优先。
例如100,要求5,有50= 50或 50= 30 +20或 50= 5+5+5+5+30,此时应该选最后一种,就是最小的值用的越多越好。假如是49,怎么算都得不到49,就取能算得到比它大的最接近的数,也就是50,所以49 = 5+5+5+5+30。
求高手帮忙
例如100,要求5,有50= 50或 50= 30 +20或 50= 5+5+5+5+30,此时应该选最后一种,就是最小的值用的越多越好。假如是49,怎么算都得不到49,就取能算得到比它大的最接近的数,也就是50,所以49 = 5+5+5+5+30。
求高手帮忙
解决方案
10
查下打包算法,但跟你的有点差异,原因是打包是不允许超出上限的
50
全部的数学规划都是需要检查全部可能的组合的,当然你可以在达成某个条件时,让枚举提前结束
然后说:这个算法可以得到可能的解,但不一定是最优解
本人不是学生,所以也没有必要按书本上的套路来。
然后说:这个算法可以得到可能的解,但不一定是最优解
本人不是学生,所以也没有必要按书本上的套路来。
static void Main(string[] args)
{
int[] data = { 100, 50, 30, 20, 10, 5 };
int total = 42;
int n = 5;
Array.Sort(data); //升序排列
int min = data[0];
foreach (var x in Descartes(data, n))
{
var t = x.Sum() - total;
if(t == 0 || (t > 0 && t < min)) Console.WriteLine(string.Join(",", x));
}
}
static IEnumerable<IEnumerable<int>> Descartes(int[] data, int num)
{
foreach (int x in data)
{
var r = new int[] { x };
if (num == 1) yield return r;
else
{
foreach (var y in Descartes(data, num - 1))
{
if(x <= y.ToArray()[0]) yield return r.Concat(y);
}
}
}
}
