假设我有一些项目,其中定义了length
和horizontal position
(两者都是常量):
1 : A
2 : B
3 : CC
4 : DDD (item 4 start at position 1, length = 3)
5 : EE
6 : F
我想垂直打包它们,产生一个尽可能小的矩形。
到目前为止,我有一些非常简单的算法循环遍历项目,并且如果将它们放在该行中则可以逐行检查(这意味着不会与其他东西发生冲突)。有时,它完美地运行(偶然)但有时会导致非最佳解决方案。
以下是上述例子(逐步)的内容:
A | A B | ACC B | ACC B | ACC B | ACC B |
DDD | DDD | FDDD |
EE | EE |
虽然最佳解决方案是:
ADDDB
FCCEE
注意:我发现在应用算法之前先按length
(降序)排序项目会产生更好的效果(但仍然不完美)。
是否有任何算法可以在合理的时间内为我提供最佳解决方案? (尝试所有可能性是不可行的)
编辑:这是一个使用排序技巧无效的例子,使用TylerOhlsen建议不起作用(除非我不理解他的答案):
1 : AA
2 : BBB
3 : CCC
4 : DD
会给:
AA BBB
CCC
DD
最佳解决方案:
DDBBB
AACCC
答案 0 :(得分:1)
只是spitballing(从我的头顶,只是伪代码)。此算法循环遍历当前行的位置,并尝试找到要放置在该位置的最佳项目,然后在此行完成时移动到下一行。使用所有项目时算法完成。
此算法性能的关键是创建一种有效的方法,可以找到特定位置的最长项目。这可以通过创建以下字典(或散列表)来完成:key = positions,value =该位置的项目的排序列表(按长度降序排序)。然后在某个位置找到最长的项目就像从该哈希表中按位置查找项目列表并从该列表中弹出顶部项目一样简单。
int cursorRow = 0;
int cursorPosition = 0;
int maxRowLength = 5;
List<Item> items = //fill with item list
Item[][] result = new Item[][];
while (items.Count() > 0)
(
Item item = FindLongestItemAtPosition(cursorPosition);
if (item != null)
{
result[cursorRow][cursorPosition] = item;
items.Remove(item);
cursorPosition += item.Length;
}
else //No items remain with this position
{
cursorPosition++;
}
if (cursorPosition == maxRowLength)
{
cursorPosition = 0;
cursorRow++;
}
}
这将导致示例1的以下步骤(在每个循环开始时)......
Row=0 | Row=0 | Row=0 | Row=1 | Row=1 | Row=1 | Row=2 |
Pos=0 | Pos=1 | Pos=4 | Pos=0 | Pos=1 | Pos=3 | Pos=0 |
| A | ADDD | ADDDB | ADDDB | ADDDB | ADDDB |
F | FCC | FCCEE |
这将导致示例2的以下步骤(在每个循环开始时)......
Row=0 | Row=0 | Row=0 | Row=1 | Row=1 | Row=1 | Row=2 |
Pos=0 | Pos=2 | Pos=4 | Pos=0 | Pos=1 | Pos=3 | Pos=0 |
| AA | AACCC | AACCC | AACCC | AACCC | AACCC |
DD | DDBBB |
答案 1 :(得分:-2)
这是一个经典的背包问题。正如@amit所说,它是NP-Complete。最有效的解决方案是利用动态规划来解决。
维基百科页面是一个非常好的开始。我从未实施任何算法来解决这个问题,但我已经研究过它与扫雷游戏的关系,这也是NP-Complete。