2017-07-03 68 views
1

我有以下對象:尋找複雜項目的最佳組合?

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對象和Clothing的集合。這個集合有許多Clothing對象的每個Slot。例如,它可能是這樣的:

MyCloset = { GREEN_HAT, RED_VEST, BLACK_VEST, 
BLUE_JEANS, BROWN_PANTS, RED_SHOES, BLACK_HAT, BLUE_GLOVES, PURPLE_VEST } 

在我的節目的現實,還有很多更多的項目不僅僅是這些,但是這僅僅是一個簡單的例子。

問題:

我需要找到這些衣服,導致最高gradeOutfit得分的組合。這意味着我的Person將必須確保他每Clothing物品與其他Clothing物品(在限制範圍內,例如不可能戴兩個帽子,因爲它們都是HEADSlot)都會嘗試。一個Person不能有gradeOutfit呼叫,直到他們每Slot穿戴Clothing項目。

我在想遞歸是做這件事的最好方法,但是如果我有足夠數量的項目,我想我會很快得到堆棧溢出。我試着迭代地做,但我似乎無法找到一個很好的簡單方法來循環一切。我的程序基本上看起來像

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(); 
} 

但我知道這只是一個可怕的方法。爲了確保每件衣服都與其他服飾產品搭配,我需要更多的循環邏輯。無論我嘗試什麼,它都會變成意大利麪代碼。我還需要避免兩次穿着同一套服裝,並確保沒有任何服裝組合被遺忘。

什麼是最好的辦法來處理這樣的事情?

+0

顏色或服裝的分數是否獨立? –

+0

@AakashVerma不,「gradeOutfit」分數是一個複雜的算法,完全取決於裝備。例如,有兩件'RED'項目的服裝得分較高,但如果RED項目靠近海誓山盟,則得分較低。假設不同的服裝可能導致完全不同的分數。 – Hatefiend

+1

我很抱歉,我不完全瞭解這個問題,但我認爲對於插槽枚舉中的每個項目,您都有一個集合。然後,你想從每個藏品中拿出一件物品,並將其稱爲西裝。然後,這個人穿上那件衣服,然後你評價它。如果是這種情況,你需要列出所有的組合並遍歷它。列出所有組合都很容易。看到這個鏈接http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/。你將不得不使用一些調整,而不是輸入數組中的每個元素,引用集合項 –

回答

1

這是一個問題mathematical optimization的一個例子。您似乎已具備目標功能(計算gradeOutfit分數的函數 - 以輸入五個衣服,每個插槽一個爲參數),並且您需要一些約束(例如,每個衣服以5個組合爲屬於不同的插槽)。您需要一個Java解算器庫來執行此操作。如果你的目標函數是線性的,一個線性求解器就可以做到。由於我只有商業解決方案的經驗,我不能推薦一個開源的,選項列表可以找到here

一種更簡單(但不是非常優雅的)的方式,沒有一個求解:

  1. 創建5套服裝的對象,每個插槽(您可以使用Java HashSet的這個)。
  2. 迭代所有組合,每次從5組中的每組中取一個項目。您需要n1 x n2 x n3 x n4 x n5個組合,其中ni是每個插槽的服裝實例數。

在我看來,gradeOutfit函數不應該是Person類的一部分 - 因爲它實際上是一個服裝的屬性,而不是一個人(即兩個具有相同服裝的人具有完全相同的分數)。我更喜歡有一個Outfit類,並把它放在那裏。

+0

好的,gotcha。我喜歡5個'Set'的想法,但這是否意味着我基本上有四個嵌套'for'循環(循環每個'Set')? – Hatefiend

+0

@Hatefiend是的,這不是很優雅,但可以工作,如果項目的數量是合理的(否則,組合可能太多,不能容納在內存中)。更優雅的方式在[這裏](https://stackoverflow.com/a/2419399/5102627)進行了描述。 –

-2

用於枚舉,必須使用在其上的方法「的值()」,以循環:

For (clothe c: clothes.values()) 
+1

我知道這一點,但不幸的是,這並不能幫助我解決這個問題。 – Hatefiend

+0

你可以嘗試fork/join框架,它允許你創建遞歸任務並將工作分解成不同的線程 –

+0

我會這樣做以獲得額外的性能,但是現在我無法解決實際上在每個組合中循環的算法。 – Hatefiend

0

您的數據結構創建非常糟糕。

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 
+1

我的'衣服'不能成爲枚舉,因爲它的成員可能會發生變化。爲了簡單起見,我沒有在原來的文章中列入。另外'//爲所有服裝組合創建一個循環'是我的問題所要求的。我不能想出一個強大的算法。 – Hatefiend

+0

您已經爲它們設置了名稱。要麼他們是枚舉和有名字,或者他們不是,他們沒有。我再次重複 - 你不瞭解你自己的數據結構,你真的沒有什麼可說的。 – Gangnus