我为我的问题实施了基于回溯的解决方案,我在之前的帖子中指定了这个问题: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;
}
非常感谢任何建议。