c#预定义值是否可以加总为某个值
我有一个预定义int值的列表c#预定义值是否可以加总为某个值,c#,math,C#,Math,我有一个预定义int值的列表 List<int> values = new List<int>() { 1, 5, 7, 12, 20 }; 如何解决此问题?您必须从列表中获取所有组合,然后检查总和是否等于提供的值: 创建扩展方法以从值列表中获取组合(这将在稍后帮助您) 你的尝试在哪里?这些值可以重复使用还是只能重复使用一次?你能提供你所期望的输入/输出样本吗?@brijber否,如果这些值不包含1这听起来像是一系列与硬币/兑换相关的数学问题;基本上,您必须实现一个算法
List<int> values = new List<int>() { 1, 5, 7, 12, 20 };
如何解决此问题?您必须从列表中获取所有组合,然后检查总和是否等于提供的值: 创建扩展方法以从值列表中获取组合(这将在稍后帮助您)
你的尝试在哪里?这些值可以重复使用还是只能重复使用一次?你能提供你所期望的输入/输出样本吗?@brijber否,如果这些值不包含
1
这听起来像是一系列与硬币/兑换相关的数学问题;基本上,您必须实现一个算法并进行尝试。在n
候选的最坏情况下,对n
位进行二进制穷举扫描就足够了,而且非常容易实现(这只是循环和位掩码的),因此:如果n
很小,这将是一个便宜的选择。随着n
的增加,您需要更好的选择。当然,你可以先做一个完整的计算,看看是否可能。
public bool canBeSummed(int value)
{
//Can any of the values in values sum up to value?
}
public static class ExttensionMethods
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
public bool CanBeSummed(int value, int[] values)
{
if (values.Contains(value)) return true;
var smaller = values.Where(x => x <= value);
if (!smaller.Any()) return false; // all values are bigger than value
var count = smaller.Count();
if (count == 1) return false; // Only 1 number and it is not value since values.Contains(value) has to be false
// Check all combinations from items (from 2 to x items where x is number of items in smaller list
return Enumerable.Range(2, count - 1).Any(x => smaller.Combinations(x).Any(c => c.Sum() == value));
}
public static object[] SumTest =
{
new object[] {6, true, new int[] {1, 5, 7, 12, 20}},
new object[] {37, true, new int[] {1, 5, 7, 12, 20}},
new object[] {9, false, new int[] {1, 5, 7, 12, 20}}
};
[TestCaseSource("SumTest")]
public void Test(int value, bool expectedResult, int[] values)
{
Assert.AreEqual(expectedResult, CanBeSummed(value, values));
}