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是的,这不是很优雅,但如果项目的数量合理(否则,组合可能太多而无法保存在内存中),它可以工作。描述了一种更为优雅的方式。MyClothing
不能是枚举,因为其成员可能会发生更改。为了简单起见,我没有把它包括在我的原始帖子中。另外,//我的问题是为所有装备的组合制定一个周期。我
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