【问题标题】:How to identify a set of objects from a large number of possible set combinations; efficient structures or models如何从大量可能的集合组合中识别出一组对象;有效的结构或模型
【发布时间】:2018-04-13 23:35:08
【问题描述】:

我一直在与一个问题作斗争,我似乎可以弄清楚如何解决它。我不会给出确切的问题,但我会将其翻译成更简单的形式。这是我想出的最简单的形式:

问题:

您有一个具有一些属性的对象类型:例如。对象 OBJ(p1, p2, z)

你有4套:A、B、C、D;它由上述对象组成。每组有 80 个对象。 (80 个 A 对象,80 个 B 对象,依此类推。这是一个数据库。)

作为输入,我给出 Z = zA + zB + zC + zD。在单词中,Z 是集合中'z' 的总和。

我对看起来像 R(Ax, Bx, Cx, Dx) 的结果集感兴趣,其中“x”代表索引(可以是 1 到 80)。

最大的那个。公式:(大约:D,它的一个数字)

最大 = coef1*(Ap1+Bp1+Cp1+Dp1) + coef2*(Ap2+Bp2+Cp2+Dp2)

coef1 和 coef2 - 系数; A、B、C、D OBJ 对象; p1 和 p2 对象属性。

我是怎么做的;也许有更好的方法??

我将 Z 小于或等于给定 Z 的所有结果集放在一个列表中。前 R1(A1、B1、C1、D1); R2(A1,B1,C1,D2)等等。 80x80x80x80 = 41 百万组合(大约)

然后我在列表中搜索使用上述公式计算的最大 SET。

我需要什么

  1. 当结果列表太大时,我在创建结果列表时出现堆栈溢出(它最多可以有 4100 万个条目,它会在大约(最多)60 万个条目后破裂)

  2. 计算需要这么长时间(找到最大的集合),我怎样才能减少时间(线程,smth else?)

  3. 全新的解决方案,解决问题。

我用 C# (Visual Studio) 编写代码。我不是在寻找解决这个问题的完整代码,而是寻找指南和/或可能的新方法。我认为我的方法不太适合它。

谢谢!

这就是我现在的做法:

public static void CalculateArmorStats(string selectedHead, string selectedChest, string selectedHands, string selectedLegs)
    {
        #region variable
        double strike; double slash; double thrust; 
        double magic; double fire; double lightning; double dark; 
        if (!selectedHead.Contains("Name =")) selectedHead = "Name ='" + selectedHead + "'";
        if (!selectedChest.Contains("Name =")) selectedChest = "Name ='" + selectedChest + "'";
        if (!selectedHands.Contains("Name =")) selectedHands = "Name ='" + selectedHands + "'";
        if (!selectedLegs.Contains("Name =")) selectedLegs = "Name ='" + selectedLegs + "'";
        MainWindow.possibleArmors = MainWindow.possibleArmors + 1;
        #endregion variable

        #region calculate stats  
        strike = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(4).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(4).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(4).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(4).ToString());
        slash = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(5).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(5).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(5).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(5).ToString());
        thrust = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(6).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(6).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(6).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(6).ToString());
        magic = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(7).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(7).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(7).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(7).ToString());
        fire = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(8).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(8).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(8).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(8).ToString());
        lightning = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(9).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(9).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(9).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(9).ToString());
        dark = double.Parse(MainWindow.dbHead.Select(selectedHead).Single().ItemArray.ElementAt(10).ToString())
        + double.Parse(MainWindow.dbChest.Select(selectedChest).Single().ItemArray.ElementAt(10).ToString())
        + double.Parse(MainWindow.dbHands.Select(selectedHands).Single().ItemArray.ElementAt(10).ToString())
        + double.Parse(MainWindow.dbLegs.Select(selectedLegs).Single().ItemArray.ElementAt(10).ToString());
        #endregion calculate stats

        #region calculate armor
        if (strike + slash + thrust > MainWindow.physicalVerifier)
        {
            MainWindow.physicalVerifier = strike + slash + thrust;
            MainWindow.SELECTEDARMOR[0].headArmor = selectedHead;
            MainWindow.SELECTEDARMOR[0].chestArmor = selectedChest;
            MainWindow.SELECTEDARMOR[0].handsArmor = selectedHands;
            MainWindow.SELECTEDARMOR[0].legsArmor = selectedLegs;              
        }
        if (magic + fire + lightning + dark > MainWindow.elementalVerifier)
        {
            MainWindow.elementalVerifier = magic + fire + lightning + dark;
            MainWindow.SELECTEDARMOR[1].headArmor = selectedHead;
            MainWindow.SELECTEDARMOR[1].chestArmor = selectedChest;
            MainWindow.SELECTEDARMOR[1].handsArmor = selectedHands;
            MainWindow.SELECTEDARMOR[1].legsArmor = selectedLegs;
        }
        if (strike + slash + thrust + 0.7 * (magic + fire + lightning + dark) > MainWindow.overallVerifier)
        {
            MainWindow.overallVerifier = strike + slash + thrust + 0.7 * (magic + fire + lightning + dark);
            MainWindow.SELECTEDARMOR[2].headArmor = selectedHead;
            MainWindow.SELECTEDARMOR[2].chestArmor = selectedChest;
            MainWindow.SELECTEDARMOR[2].handsArmor = selectedHands;
            MainWindow.SELECTEDARMOR[2].legsArmor = selectedLegs;
        }
        #endregion  calculate armor            
    }

然后我调用以下 FOR(计算需要 3 分钟 - 我怎样才能减少这个时间):

        foreach (ArmorObject chestItem in MainWindow.CHESTS)
        {
            foreach (ArmorObject legsItem in MainWindow.LEGS)
            {
                foreach (ArmorObject handsItem in MainWindow.HANDS)
                {
                    if (availableWeight >= double.Parse(chestItem.weight.ToString()) + double.Parse(legsItem.weight.ToString())
                        + double.Parse(handsItem.weight.ToString()))
                    {
                        string selectedHead = MainWindow.mySlectedArmorName.head.Content.ToString();
                        string selectedChest = chestItem.name;
                        string selectedHands = handsItem.name;
                        string selectedLegs = legsItem.name;
                        CalculateArmorStats(selectedHead, selectedChest, selectedHands, selectedLegs);
                    }
                }                                
            }                        
        }

好的,再次更新。 所以我做了以下事情:

我将 4 个数据库(头部、胸部、...)放在 4 个对象列表中。 -> 这会使程序启动较慢,但幅度不大。

现在,当我计算数据时,我不需要询问数据库(区域计算统计信息)-> 这将我在此处发布的 FOR 时间从 3 分钟减少到 3 秒。

但是我仍然不满意或不同意这是一个解决方案(它确实对我有帮助),因为与现实生活中的项目相比,我的数据库很小:D。

【问题讨论】:

  • 最好根据您的尝试方式向我们提供code,给我们一堆xyz 变量并没有帮助。

标签: java c# math data-structures processing-efficiency


【解决方案1】:

如果我理解正确,你有

  • 具有p1p2z 三个属性的对象,
  • 四组ABCD,每组80个以上对象,
  • 两个常量k1k2
  • 一个函数f(a,b,c,d)=k1*(a.p1+b.p1+c.p1+d.p1) + k2*(a.p2+b.p2+c.p2+d.p2),它将A×B×C×D的元素映射到一个值,
  • 一个函数g(a,b,c,d)=a.z+b.z+c.z+d.z,将A×B×C×D的元素映射到一个值,
  • 输入值Z
  • 一个值BIGGEST,它是f(a,b,c,d) 在集合A×B×C×D 上的最大值(或者也许-我没有完全从您的问题公式中得到这一点-仅在满足@ 的A×B×C×D 的那些元素上987654339@),

你想计算一个集合S,它包含A×B×C×D的所有元素,f(a,b,c,d)=BIGGESTg(a,b,c,d)≤Z

如果是这种情况,您可以将问题分为两部分:

  1. 找到值BIGGEST。这不需要太多内存,因为您可以存储目前找到的最高值并在找到更高值时更新它。
  2. 生成集合S:已经计算出BIGGEST,这也很容易。如果不存储找到的集合S的元素,这也不需要太多内存。

【讨论】:

  • 添加了我当前的代码。如果您有任何建议,我将不胜感激。 for 必须计算 90x90x90 的可能性,我还发布了我的微积分方法。我想将时间缩短到一分钟以下。不知道该怎么做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
  • 1970-01-01
相关资源
最近更新 更多