Это называется проблемой суммы подмножеств и считается сложной проблемой в информатике. Не сложно, как трудно, но трудно сделать быстро - вы можете легко написать алгоритм для этого, но для значительных входных данных это легко займет миллиарды лет.
Если вас устраивает медленное решение, которое возможно только для небольших входов, попробуйте что-то вроде этого:
Создание всех подмножеств списка ввода.
Для каждого поднабора вычислите сумму элементов в этом подмножестве.
Возвращает первое подмножество, для которого совпадает сумма.
Вот метод, который возвращает все подмножества (на самом деле подпоследовательности , потому что он поддерживает порядок элементов, хотя в вашем случае это не имеет значения):
/// <summary>
/// Returns all subsequences of the input <see cref="IEnumerable<T>"/>.
/// </summary>
/// <param name="source">The sequence of items to generate
/// subsequences of.</param>
/// <returns>A collection containing all subsequences of the input
/// <see cref="IEnumerable<T>"/>.</returns>
public static IEnumerable<IEnumerable<T>> Subsequences<T>(
this IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullException("source");
// Ensure that the source IEnumerable is evaluated only once
return subsequences(source.ToArray());
}
private static IEnumerable<IEnumerable<T>> subsequences<T>(IEnumerable<T> source)
{
if (source.Any())
{
foreach (var comb in subsequences(source.Skip(1)))
{
yield return comb;
yield return source.Take(1).Concat(comb);
}
}
else
{
yield return Enumerable.Empty<T>();
}
}
Так что теперь вы можете написать что-то вроде этого ...
var result = list.Subsequences()
.FirstOrDefault(ss => ss.Sum(item => item.Value) == sum);