在多个项目中查找总计为0的值

时间:2018-11-16 10:58:59

标签: c# excel performance knapsack-problem subset-sum

我必须在足够大的列表中找到每个子集,这些正/负和十进制数的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;
            }

} }

0 个答案:

没有答案