2016-11-06 11 views
2

私はボックスに収まるアイテムの数に制約があり、移動する前にできるだけ多くのアイテムをボックスに収めなければならない欲張りアルゴリズムを作成しようとしています(すなわち、各箱の重量を最大化する)。Python。貪欲アルゴリズム、2つのループのリストを繰り返します。

私はこれを2つの同一のリストを作成することで解決しようとしています。a_listb_listとしましょう。

ここでは、各ボックスの制約は10です。たとえば、次のボックスに移動する前に、最初のアイテム(9)のみを1つに収めることができます。以下のボックスには、8 + 2

各ボックスには、現在の1がそれに嵌め込まさらにアイテムを持つことはできません一度私は、次のボックスに進むことができ

list_ = [[9], [8,2],[6,4].....] 

すなわちメインリスト内のリストで含まれている必要があります。

私は2つのリストを反復しようとしていますが、アイテムを削除する方法がわからないので、複数回表示されないようにlist_にしてください。

私は近づいていますが、私は2つのアイテムが2回出てきますが、1つはまったく出てこないのです。

私のリストを降順でソートしても、すべてのボックスが最適ではない場合もありますが、そのうちの1つに値 '2'のアイテムが1つしかありません。私はそれがループと関係があると知っていますが、なぜそれが降順で項目を通過していないのか分かりません。

limit = 10 
list_ = [[]] 

for i in a_list: 
    for j in b_list:    

     if sum(l[-1]) + i + j <= limit: 

      l[-1].append(i) 
      l[-1].append(j) 
      b_list.remove(j) 

     elif sum(l[-1]) + j <= limit: 
      l[-1].append(j) 
      b_list.remove(j) 

     else: 
      l.append([]) 
+0

重要な問題は、項目を削除しながらリストを繰り返していることです。常にそれを避けてください。 –

+0

ご理解ください、ありがとうございます。私は内側のループからだけ項目を削除していますが、外側は削除していません。それはまだ問題ですか? – Monika

+0

いくつのボックスがありますか? – Ukimiku

答えて

0

私はあなたがa_listb_listを使用していることだと思う唯一の理由は、あなたがケースである必要はないボックスごとに2つのアイテムを、選択する必要が想定していることです。

私はあなたが単一のリストを使用し、どの項目が追加されたかを追跡するためにリストインデックスベースのアプローチを使うべきだと思います。

また、削除時に問題が発生するため、ループ中に削除の混乱を避けるために、-1に追加された項目を設定し、各パスの後にそれらをフィルタリングしてみてください。

ここではソリューションコードの共有に抵抗していますが、必要に応じてpingしてください。

+0

ありがとうBitonator、それは非常に感謝します。私が2つのリストを使用してきた理由は、値が小さいアイテムを追加するためにリストをさらに反復する必要があるのを解消しようとしていたからです。例:私が9,8,7などから降下しているときに、時にはボックスを埋めるために '2'にする必要があります。 – Monika

+0

OK、そうではなく、1回のパスでできるだけ多くのアイテムをボックスに追加しようとしたら、もう一度それらのアイテムを削除するパスを実行してください。 – Bitonator

+0

私はおそらく何か不足しています。内部ループ内のアイテムを削除することによって、追加したアイテムを削除する別のパスを作成する必要があると私がしてきたことではありませんか? – Monika

0

リストを反復するときにリストを変更することは、常に挑戦です。ここでは、私が一般的に言及していないwhileループを使用する1つのソリューションがありますが、ここで問題なく動作するはずの簡単なアルゴリズムです。

whileループは、初期リストに要素が残っているかどうかをチェックします。次に、リストの最初の要素をポップ(削除して保存)し、リストの残りの部分を繰り返して、合計の条件を満たす追加の要素を検索します。ある要素が見つかった場合、それはサブリストに追加され、そのインデックスが記録されます。 forループの最後に、サブリストが出力リストに追加され、記録されたインデックスは、逆順でのが削除されます。

a_list = [9, 8, 6, 4, 3, 2, 2, 2] 
constraint = 10 

out = [] 
while a_list: 
    # grab first element of a_list and reset the list of 
    # to pop from a_list to pop from a_list 
    sub_out = [a_list.pop(0)] 
    pop_list = [] 

    for i,a in enumerate(a_list): 
     if a+sum(sub_out) <= constraint: 
      sub_out.append(a) 
      pop_list.append(i) 

    # append the sub_list to the output list 
    out.append(sub_out) 
    # remove each item in the pop_list in the reverse order 
    for i in reversed(pop_list): 
     a_list.pop(i) 

#output: 
>>> out 
[[9], [8, 2], [6, 4], [3, 2, 2]] 
+0

ありがとう! whileループについても私は夢中ではないが、それはまさに私が最後の半時間で遊んできたものだ。別のリストでコードを試してみましたが、完璧です。とても有難い! – Monika

+0

ようこそ。この解決策が完了したと思われる場合は、その質問に回答としてマークすることを忘れないでください。 – James

+0

ありがとうございます。実際には、元の例は辞書(つまり、{x:9、z:7など)であり、リストではなく、リストの最終リストにキーを追加することになっています。すなわち、[[x]、[y、z]]など)。簡単なので私の元の投稿の値を使用しましたが、キーではなく値をポップする必要がある場合、あなたの例で '列挙'メソッドをどのように置き換えるべきかわかりません。その価値に気づいている間にキーを反復するのに使用できる同等のものはありますか?ありがとうございました。 – Monika

関連する問題