以前の投稿で指定した問題に対して、バックトラッキング ベースのソリューションを実装しました: Packing items into Fixed number of bins
(Bin は、vector<int>
sum() などの追加メソッドを備えたデータ型の単純なラッパーです)
bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned index, unsigned bin_capacity)
{
if (bin_capacity - items.front() < 0) return false;
if (index < items.size())
{
//try to put an item into all opened bins
for(unsigned i = 0; i < bins.size(); ++i)
{
if (bins[i].sum() + items[index] + items.back() <= bin_capacity || bin_capacity - bins[i].sum() == items[index])
{
bins[i].add(items[index]);
return backtrack(items, bins, index + 1, bin_capacity);
}
}
//put an item without exceeding maximum number of bins
if (bins.size() < BINS)
{
Bin new_bin = Bin();
bins.push_back(new_bin);
bins.back().add(items[index]);
return backtrack(items, bins, index + 1, bin_capacity);
}
}
else
{
//check if solution has been found
if (bins.size() == BINS )
{
for (unsigned i = 0; i <bins.size(); ++i)
{
packed_items.push_back(bins[i]);
}
return true;
}
}
return false;
}
このアルゴリズムは非常に高速に動作しますが、大規模なデータ セットではスタック オーバーフローが発生する傾向があります。
それを改善するためのアイデアや提案を探しています。
編集:
明示的なスタックを使用して反復アプローチを試みることにしましたが、私のソリューションは期待どおりに機能しません - 時々間違った結果が得られます。
bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned index, unsigned bin_capacity)
{
stack<Node> stack;
Node node, child_node;
Bin new_bin;
//init the stack
node.bins.add(new_bin);
node.bins.back().add(items[item_index]);
stack.push(node);
item_index++;
while(!stack.empty())
{
node = stack.top();
stack.pop();
if (item_index < items.size())
{
if (node.bins.size() < BINS)
{
child_node = node;
Bin empty;
child_node.bins.add(empty);
child_node.bins.back().add(items[item_index]);
stack.push(child_node);
}
int last_index = node.bins.size() - 1;
for (unsigned i = 0; i < node.bins.size(); i++)
{
if (node.bins[last_index - i]->get_sum() + items[item_index]+ items.back() <= bin_capacity ||
bin_capacity - node.bins[last_index - i]->get_sum() == items[item_index])
{
child_node = node;
child_node.bins[last_index - i]->push_back(items[item_index]);
stack.push(child_node);
}
}
item_index++;
}
else
{
if (node.bins() == BINS)
{
//copy solution
bins = node.bins;
return true;
}
}
}
return false;
}
どんな提案でも大歓迎です。