我需要找到所有可能的非重叠项目组合,这些项目被分组到存储桶中。可以有任意数量的桶,每个桶可以包含任意数量的桶。有效组合将恰好包含每个存储桶中的1个项目。
bucket item start end
========================
|-- I1 1 5
B1----|-- I2 6 9
|-- I3 15 20
|-- I4 6 9
B2----|-- I5 10 14
|-- I6 14 25
|-- I7 1 14
B3----|-- I8 26 40
|-- I9 1 20
|-- In ...
Bn ...
例如,我们可以做项目1,4,8; 1,5,8; 1,6,8; 2,5,8; 2,6,8; 3,4,8;和3,5,8。
我们可以观察到项目9没有出现在组合中,因为它与桶1中的所有项目重叠,没有任何选项。
如何有效地解决这个问题?我正在浏览器JavaScript中实现它。
答案 0 :(得分:1)
蛮力方法是生成桶的笛卡尔积,并过滤掉任何无效的。所以,假设你的桶只是项目列表,那就是:
var cp = _.flatten(_.flatten(_.map(B1, function(item1) {
return _.map(B2, function(item2) {
return _.map(B3, function(item3) {
return [item1, item2, item3];
});
});
}), true), true);
将为您提供3桶的笛卡尔产品。
_.filter(cp, function(tuple) {
return !overlaps(item1, item2) && !overlaps(item1, item3) && !(overlaps(item2, item3);
});
将过滤掉您不想要的(给定合适的重叠定义)。
function overlaps(a, b) {
return a.lower > b.upper || b.lower > a.upper;
}
您可以将过滤器推广到任意数量的间隔,方法是将笛卡尔积转换为递归调用,计算_.first(args)在_.rest(args)的笛卡尔积上的展平展开。
您可以通过生成所有可能的对并将!_.any(pairs, function(pair) { return overlaps.prototype.apply(undefined, pair); });
调用来将过滤器推广到任意数量的间隔。