2013-03-20 97 views
2

可以說,我在List中擁有自定義對象的集合。每個對象的持續時間屬性設置爲幾分鐘(10分鐘或15分鐘或45分鐘等),如何根據某些條件從現有集合中創建新列表

我必須在3小時的列表中對它們進行分組。那就是ListA將會收集持續時間總和應該等於3小時等的對象。但最終列表需要/不需要堅持3小時(即可能更小或相等)

我應該使用哪種算法從列表中讀取對象並基於總共3小時的時間創建新列表。

這裏的困難可能是,可以說我有30分鐘的對象中的5分和45分鐘的對象中的2分。在ListA中如果我在閱讀時添加了5個30分鐘(6 * 50 = 150)的對象,並且我不能添加1個45分鐘的對象。因爲那不會等於3個小時。我會先增加45分鐘對象中的2個,然後再增加30分鐘中的3個對象(2 * 45 + 3 * 30 = 3小時),並將另一個對象放在另一個列表中。

感謝您的閱讀。

+0

我認爲列表中的值是隨機排列的? – SpaceApple 2013-03-20 09:29:22

+3

我不確定我是否完全明白了。但你知道knapsak問題嗎? http://en.wikipedia.org/wiki/Knapsack_problem – 2013-03-20 09:29:25

+0

@SpaceApple:你可以採取隨機順序。 – user2190141 2013-03-20 09:32:22

回答

1

如果您嘗試首先存儲大對象並以較小的值完成,可能很容易。

下面是一個簡單的代碼我爲你而造,並能正常工作:

static void Main(string[] args) 
    { 
     // data 
     List<Int32> listElement = new List<Int32>() { 10, 20, 10, 30, 45, 10, 20, 30, 40, 50, 60, 40, 30, 50, 60, 70, 80, 90, 20, 30, 10, 50, 60, 40, 60, 80, 90, 60, 80, 70, 80, 90, 90, 50 }; 
     Int32 MaxStack = 180; 

     // result 
     List<List<Int32>> listResult = new List<List<Int32>>(); 

     // process 
     foreach (Int32 element in listElement.OrderByDescending(i => i)) 
     { 
      List<Int32> listToStore = listResult.Where(l => l.Sum() + element <= MaxStack).FirstOrDefault(); 
      if (listToStore == null) 
      { 
       listToStore = new List<Int32>(); 
       listResult.Add(listToStore); 
      } 

      listToStore.Add(element); 
     } 

     // view 
     foreach (List<Int32> list in listResult) 
     { 
      Console.Write("List " + (listResult.IndexOf(list) + 1) + "[total " + list.Sum() + "]: ");     
      foreach (Int32 element in list) 
      { 
       Console.Write(element.ToString() + " "); 
      } 

      Console.WriteLine(); 
     } 

     Console.ReadKey(); 
    } 

對於這個例子,它是在控制檯,使用的Int32對象,但它是複雜的對象相同。

所有的事情是從大到小讀取對象列表,並找到可存儲它的第一個商店列表。

結果是:

List 1[total 180]: 90 90 
List 2[total 180]: 90 90 
List 3[total 180]: 80 80 20 
List 4[total 180]: 80 80 20 
List 5[total 180]: 70 70 40 
List 6[total 180]: 60 60 60 
List 7[total 180]: 60 60 50 10 
List 8[total 180]: 50 50 50 30 
List 9[total 175]: 45 40 40 30 20 
List 10[total 90]: 30 30 10 10 10 

編輯:如果你想盡可能多的在180名單,這是你的過程和視圖之間添加一個(quicky和小喬)代碼:

 // switching element for better fill 
     List<List<Int32>> unfilledlist = listResult.Where(l => l.Sum() < MaxStack).ToList(); 
     // truncate original result 
     unfilledlist.ForEach(l => listResult.Remove(l)); 

     while (unfilledlist != null && unfilledlist.Count > 1) 
     { 
      List<Int32> list = unfilledlist.First(); 
      unfilledlist.Remove(list); 

      foreach (Int32 element in list) 
      { 
       Int32 needed = MaxStack - list.Sum() + element; 
       Boolean isFound = false; 

       foreach (List<Int32> smallerlist in unfilledlist) 
       { 
        List<Int32> switchingList = new List<int>(); 

        // searching how to fill what we needed 
        foreach (Int32 e in smallerlist.OrderByDescending(i => i)) 
        { 
         if (e + switchingList.Sum() <= needed) 
          switchingList.Add(e); 
        } 

        // we found a possible switch 
        if (switchingList.Sum() == needed) 
        { 
         // moving first element 
         list.Remove(element); 
         smallerlist.Add(element); 

         // moving element 
         switchingList.ForEach(e => { smallerlist.Remove(e); list.Add(e); }); 
         isFound = true; 
         break; 
        } 
       } 

       if (isFound) 
        break; 
      } 

      listResult.Add(list.OrderByDescending(i => i).ToList()); 
     } 

     // completing result with lists that are not with sum 180 
     unfilledlist.ForEach(l => listResult.Add(l.OrderByDescending(i => i).ToList())); 

我不滿意這個代碼,但它似乎工作

新結果:

List 1[total 180]: 90 90 
List 2[total 180]: 90 90 
List 3[total 180]: 80 80 20 
List 4[total 180]: 80 80 20 
List 5[total 180]: 70 70 40 
List 6[total 180]: 60 60 60 
List 7[total 180]: 60 60 50 10 
List 8[total 180]: 50 50 50 30 
List 9[total 180]: 40 40 30 30 20 10 10 
List 10[total 85]: 45 30 10 
+0

這不是唯一的解決方案,但它看起來不錯;) – Xaruth 2013-03-20 11:04:17

+0

@ Xaruth:第9個列表有175個,小於180.這一個將不起作用。我們能解決嗎? – user2190141 2013-03-20 11:23:39

+0

您可以分析列表,並在列表之間切換不超過180的項目(列表中有180個項目以更好的方式填充,並帶有更大的項目)。例如,將列表9中的45和列表10中的30 + 10 + 10進行切換。但是,這是一個好的方法嗎?您無法確定始終可以以精確的180度填充所有列表(例如:objects {100,100,100,100,100,50,50,50})。相反,如果你有很多小件物品,你不會有沒有空缺的名單。 – Xaruth 2013-03-20 12:32:07

相關問題