所以我有 N 项目的权重: w [1],w [2],.. w [N] ,还有几个包可以容纳重量 M 。
问题是:如何对项目进行分组,以便我能够所有使用最少个数量的包<?p>?
测试用例:
重量 w [i] = [40,6,4,42,8,43,4,3,19,30]的物品。
行李可以 M = 50。
可接受的答案:(40,6,4)(42,8)(43,4,3)(19,30)
答案 0 :(得分:2)
您的问题是线性箱包装的特殊情况,其中重量都是非负的。 在这种特殊情况下,贪婪的First-Fit算法总能产生最佳解决方案。
&#34;证明&#34;在这些课堂笔记上给出的不正确: http://cs.nyu.edu/~yap/classes/funAlgo/05f/lect/l5.pdf
正如@Fede所指出的,如果我们重新排列示例的输入并应用First-Fit算法,我们会得到一个非最佳结果:
w [i] =(43,6,4,42,8,40,4,3,19,30),M = 50
FF产量(43,4),(4,42),(8,40),(4,3,19),(30)为5袋。
我会删除这个答案以避免不彻底检查的耻辱,但我希望这可以防止其他人陷入同样的陷阱。
答案 1 :(得分:2)
第一次适合贪婪并不能保证最佳包装。使用提供的样品,第一次贴合可以尝试将重量为43的物品与重量为6的物品包装在一起,然后生成的包装将不少于5个包装而不是4个。
动态编程可能是一个非常有效的解决方案,它可以利用为较小的项目集解决问题。我将在这里提出一个简单的回溯,如果性能不可接受,你可以稍后进行优化。
我对此的看法如下。您可以编写一个简单的递归,使用以下规则为每个项目分配包ID:
这样的事情会实现这套规则。
int[] FindBestPackageForItems(int[] weights, int N, int M) {
// in the worst scenario, you'll have N packages
int lowestNumberOfBags = N;
int[] bestPacking = new int[N];
for (int i = 0; i < N; i++)
bestPacking[i] = i;
int[] weightInEachBag = new int[N];
int[] currentPacking = new int[N];
currentPacking[0] = 0; // First item is always in package 0
weightInEachBag[0] = weights[0];
int currentItem = 1; // Item 0 is already in bag 0, the next item to pack will be the item 1
int usedBags = 1; // The first bag is already used by the first item
PutItemsInBags(weights, N, M, currentPacking, weightInEachBag, currentItem, usedBags, bestPacking, ref lowestNumberOfBags);
return bestPacking;
}
void PutItemsInBags(int[] weights, int N, int M, int[] currentPacking, int[] weightInEachBag, int currentItem, int usedBags, int[] bestPacking, ref int lowestNumberOfBags) {
if (currentItem == N) {
assert(usedBags < lowestNumberOfBags);
for (int i = 0; i < N; i++)
bestPacking[i] = currentPacking[i];
lowestNumberOfBags = usedBags;
}
else {
for (int p = 0; p < min(usedBags + 1, lowestNumberOfBags); p++) {
if (weightInEachBag[p] + weights[currentItem] <= M) {
weightInEachBag[p] += weights[currentItem];
currentPacking[currentItem] = p;
PutItemsInBags(weights, N, M, currentPacking, weightInEachBag, currentItem+1, max(p, usedBags), bestPacking, ref lowestNumberOfBags);
weightInEachBag[p] -= weights[currentItem];
}
}
}
}