Я должен найти каждое подмножество в достаточно большом списке, 500/1000 элементов, которые являются положительными и отрицательными и являются десятичными, а сумма равна 0. Я не эксперт, поэтому я прочитал много и много статей и решений, и Затем я написал свой код. Данные поступают из таблицы Excel, и я хотел бы отметить найденные суммы там.
Код работает следующим образом:
- Изначально я нахожу все пары с суммой 0
- Затем я кладу суммы остатков в список и беру комбинации в пределах 20 предметов, поскольку я знаю, что невозможно увеличить сумму комбинации до 0
- В этих комбинациях я ищу, если одна из комбинаций суммирует 0, и сохраняет ее в списке результатов, в противном случае я сохраняю сумму в словаре в качестве ключа, а затем я буду искать, содержит ли словарь следующие суммы (поэтому я проверяю пары этих подмножеств)
- Я отслеживаю индекс, чтобы я мог добраться до ячеек и изменить их
Найти решения достаточно быстро, но когда я хочу уточнить, результаты в Excel становятся очень медленными. Я не забочусь о поиске всех решений, но я хочу найти максимально возможное за короткое время.
Что вы думаете об этом решении? Как я могу улучшить скорость? Как я могу легко пропустить суммы, которые уже взяты? И как быстро пометить ячейки в моем рабочем листе, потому что теперь здесь есть узкое место программы?
Надеюсь, это достаточно ясно :) Спасибо всем за помощь
Вот мой код части комбинации:
List<decimal> listDecimal = new List<decimal>();
List<string> listRange = new List<string>();
List<decimal> resDecimal = new List<decimal>();
List<IEnumerable<decimal>> resDecimal2 = new List<IEnumerable<decimal>>();
List<IEnumerable<string>> resIndex = new List<IEnumerable<string>>();
Dictionary<decimal, int> dicSumma = new Dictionary<decimal, int>();
foreach (TarkistaSummat.CellsRemain el in list)
{
decimal sumDec = Convert.ToDecimal(el.Summa.Value);
listDecimal.Add(sumDec);
string row = el.Summa.Cells.Row.ToString();
string col = el.Summa.Cells.Column.ToString();
string range = el.Summa.Cells.Row.ToString() + ":" + el.Summa.Cells.Column.ToString();
listRange.Add(range);
}
var subsets = new List<IEnumerable<decimal>> { new List<decimal>() };
var subsetsIndex = new List<IEnumerable<string>> { new List<string>() };
for (int i = 0; i < list.Count; i++)
{
if (i > 20)
{
List<IEnumerable<decimal>> parSubsets = subsets.GetRange(i, i + 20);
List<IEnumerable<string>> parSubsetsIndex = subsetsIndex.GetRange(i, i + 20);
var Z = parSubsets.Select(x => x.Concat(new[] { listDecimal[i] }));
//var Zfound = Z.Select(x => x).Where(w => w.Sum() ==0);
subsets.AddRange(Z.ToList());
var Zr = parSubsetsIndex.Select(x => x.Concat(new[] { listRange[i] }));
subsetsIndex.AddRange(Zr.ToList());
}
else
{
var T = subsets.Select(y => y.Concat(new[] { listDecimal[i] }));
//var Tfound = T.Select(x => x).Where(w => w.Sum() == 0);
//resDecimal2.AddRange(Tfound);
//var TnotFound = T.Except(Tfound);
subsets.AddRange(T.ToList());
var Tr = subsetsIndex.Select(y => y.Concat(new[] { listRange[i] }));
subsetsIndex.AddRange(Tr.ToList());
}
for (int i = 0; i < subsets.Count; i++)
{
decimal sumDec = subsets[i].Sum();
if (sumDec == 0m)
{
resDecimal2.Add(subsets[i]);
resIndex.Add(subsetsIndex[i]);
continue;
}
else
{
if(dicSumma.ContainsKey(sumDec * -1))
{
dicSumma.TryGetValue(sumDec * -1, out int index);
IEnumerable<decimal> addComb = subsets[i].Union(subsets[index]);
resDecimal2.Add(addComb);
var indexComb = subsetsIndex[i].Union(subsetsIndex[index]);
resIndex.Add(indexComb);
}
else
{
if(!dicSumma.ContainsKey(sumDec))
{
dicSumma.Add(sumDec, i);
}
}
}
}
for (int i = 0; i < resIndex.Count; i++)
{
//List<Range> ranges = new List<Range>();
foreach(string el in resIndex[i])
{
string[] split = el.Split(':');
Range cell = actSheet.Cells[Convert.ToInt32(split[0]), Convert.ToInt32(split[1])];
cell.Interior.ColorIndex = 6;
}
}
}