Java 找到复杂项目集合的最佳组合?

Java 找到复杂项目集合的最佳组合?,java,algorithm,object,combinations,Java,Algorithm,Object,Combinations,我有以下目标: enum Slot { HANDS, LEGS, CHEST, HEAD, FEET; } class Clothing { // The slot this piece of clothing is worn on. Slot s; // The color of the clothing, used for `gradeOutfit` Color c; } class Person { Map<Slot, Clothing>

我有以下目标:

enum Slot
{
   HANDS, LEGS, CHEST, HEAD, FEET;
}

class Clothing
{
   // The slot this piece of clothing is worn on.
   Slot s;
   // The color of the clothing, used for `gradeOutfit`
   Color c;
}

class Person
{
   Map<Slot, Clothing> body;

   // look through his outfit and give a score
   // for how well he looks
   int gradeOutfit()
   {
      return ...
   }
}
在我的程序中,除了这些,还有很多项目,但这只是一个简化的例子

问题:

我需要找到这些衣服的组合,以获得最高的
等级装备
分数。这意味着我的
员工将必须确保他试穿每件
衣服
和每件其他
衣服
物品(在限制范围内,例如,不可能戴两顶帽子,因为这两顶帽子都是为
头部
插槽
)。一个
在每个
时段都穿着
服装
之前,不能调用其
等级装备

我认为递归是最好的方法,但是如果我有足够多的项目,我会很快得到堆栈溢出。我试着反复做,但似乎找不到一个简单的方法来循环所有的事情。我的程序基本上看起来像

Person p = new Person();
for (Clothing i : MyCloset)
{
    for (Clothing h : MyCloset)
    {
        if (i == h) continue;

        if (!p.isWearing(h.slot())
        {
            p.wear(h);
        }
    }

    int score = p.gradeOutfit();
}
但我知道这只是一个可怕的方法。为了确保每件衣服都与其他衣服配对,我需要更多的循环逻辑,而不仅仅是这个。不管我怎么做,它都会变成意大利面代码。我还需要避免在同一套衣服上重复两次,并确保没有忘记任何衣服组合


最好的方法是什么?

对于枚举,必须使用“values()”方法在其上循环:

 For (clothe c: clothes.values())
这是一个问题的例子。你似乎已经有了目标函数(计算等级装备分数的函数-将五件衣服作为输入,每个插槽一件),你需要一些约束(例如,五件衣服组合中的每件衣服属于不同的插槽)。要做到这一点,您需要一个Java解算器库。如果你的目标函数是线性的,线性解算器就可以了。由于我只有商业解决方案方面的经验,我不能推荐一个开源解决方案,可以找到一个选项列表

一种更简单(但不是非常优雅)的方法,无需解算器:

  • 创建5组衣服对象,每个插槽一个(可以使用Java 为此设置哈希值)
  • 迭代所有组合,每次从5个集合中的每个集合中提取一个项目。您需要n1 x n2 x n3 x n4 x n5组合,其中ni是每个插槽的衣服实例数
    在我看来,GradeGuile函数不应该是Person类的一部分,因为它实际上是一个装备的属性,而不是一个人的属性(即两个装备相同的人的分数完全相同)。我希望有一个装备类并将其放在那里。

    您创建的数据结构非常糟糕

    enum Slot
    {
       HANDS, LEGS, CHEST, HEAD, FEET;
       numbers = new int[values.length()]
    }
    
    enum COLOR
    {
       RED,BLUE,...;
    }
    enum Clothing {
        GREEN_HAT(HEAD,GREEN), ...; 
    
        Slot slot;
        Color color;
        public static Clothing (Slot slot, Color color){...}
    }
    class Outfit extends Map <Slot, Clothing> {
        countScore(){};
        public static Outfit(){
            //foreach slot this.put(slot, Clothing.values().get(0));
        }
    }
    ... 
    int n=slot.values.length()-1;
    Outfit currentOutfit = new Outfit();
    Outfit bestOutfit = new Outfit();
    int currentActiveSlot = 0;
    // make a cycle for combination of all Outfits
    
    enum插槽
    {
    手、腿、胸、头、脚;
    数字=新的整数[values.length()]
    }
    枚举颜色
    {
    红色,蓝色,。。。;
    }
    枚举服装{
    绿色帽子(头,绿色)。。。;
    槽;
    颜色;
    公共静电服(槽、色){…}
    }
    类图{
    countScore(){};
    公共静态设备(){
    //foreach slot this.put(slot,Clothing.values().get(0));
    }
    }
    ... 
    int n=slot.values.length()-1;
    装备当前装备=新装备();
    装备最佳装备=新装备();
    int currentActiveSlot=0;
    //做一个组合所有装备的循环
    
    颜色或衣服的分数是独立的吗?@AakashVerma不,
    等级装备
    分数是一个复杂的算法,完全取决于装备。例如,有两件
    红色
    物品的装备得分较高,但如果
    红色
    物品相邻,则得分较低。假设不同的服装会导致完全不同的分数。很抱歉,我不完全理解这个问题,但我认为slot enum中的每件商品都有一个集合。然后你想从每个系列中挑选一件,称之为西装。然后p穿那套衣服的人,你给他打分。如果是这样的话,你需要列出所有的组合并迭代。列出所有组合很容易。请参阅此链接。您必须使用一些调整,而不是输入数组中的每个元素,引用它所依赖的集合项。如果每个次优装备都可以通过一次交换得到改进,那么你可以从任何装备开始,检查单次交换装备的改进情况,在发现改进时交换,在没有发现改进时停止。每次迭代取O(可能的交换=未穿衣服的数量)。如果这不是真的,你仍然可以用它来找到本地的好装备(不是最优的,但不能通过任何单一的交换来改进).我知道这一点,但不幸的是,这对我的问题没有帮助。你可以尝试使用fork/join框架,它允许你创建递归任务,并将工作划分为不同的线程。我会这样做,以获得额外的性能,但现在我无法解决实际循环每个组合的算法。当人戴上我,那么她就不能穿同样的h。当这个人穿h时,她就不能穿同样的i。也许你应该在每次你绕i圈的时候解除某人的束缚。在第一圈的时候,她会穿红色背心,但在第一圈的外面你没有p.Wear(i),所以她只穿一件衣服,这正常吗?好的,明白了。我喜欢五个
    集合
    的想法,但这是否意味着我基本上会有四个嵌套的
    for
    循环(循环通过每个
    集合
    )?@hatefind是的,这不是很优雅,但如果项目的数量合理(否则,组合可能太多而无法保存在内存中),它可以工作。描述了一种更为优雅的方式。My
    Clothing
    不能是枚举,因为其成员可能会发生更改。为了简单起见,我没有把它包括在我的原始帖子中。另外,
    //我的问题是为所有装备的组合制定一个周期。我
    
    enum Slot
    {
       HANDS, LEGS, CHEST, HEAD, FEET;
       numbers = new int[values.length()]
    }
    
    enum COLOR
    {
       RED,BLUE,...;
    }
    enum Clothing {
        GREEN_HAT(HEAD,GREEN), ...; 
    
        Slot slot;
        Color color;
        public static Clothing (Slot slot, Color color){...}
    }
    class Outfit extends Map <Slot, Clothing> {
        countScore(){};
        public static Outfit(){
            //foreach slot this.put(slot, Clothing.values().get(0));
        }
    }
    ... 
    int n=slot.values.length()-1;
    Outfit currentOutfit = new Outfit();
    Outfit bestOutfit = new Outfit();
    int currentActiveSlot = 0;
    // make a cycle for combination of all Outfits