【发布时间】:2019-06-21 12:22:42
【问题描述】:
我正在尝试编写一种算法,该算法将根据不同的输入组合“填充”车辆至其容量。问题已解决,但速度太慢,无法用于更多组合。
例如: 我有一辆容量为 10 的车辆,我有不同的座位类型(属性)组合,可以以不同的方式填充车辆(流动,或默认为 1 的正常座位容量)。此外,每个不等于 10(大于 10 被删除)的组合将被填充为流动容量,或者只是一个普通座位。像这样:
const a = [ {
name: 'wheelchair',
capacity: 0,
total: 3
}, {
name: 'walker',
capacity: 2,
total: 5
}, {
name: 'service animal',
capacity: 2,
total: 5
}];
在上面的示例中还值得注意的是,轮椅每个组合只能添加 3 次,因为它总共有 3(max) 个。轮椅的 0 容量是此特定属性的指定位置的示例,该位置不占用任何其他流动座位。
我为此尝试了几种不同的方法,并且我的算法适用于这种特定组合,或者即使我添加了更多。但是,如果我添加一个总数为 10 且容量为 1 的属性,这将使总可能性增加一个数量级,并极大地减慢算法速度。在我的方法中,我找到了不同的排列,然后过滤掉重复项以找到组合,如果有办法只找到组合,也许它会减少计算负载,但我想不出办法。我有一种输出需要查看的特定方式,即底部的输出,但是我可以控制输入,并且可以在必要时进行更改。非常感谢任何想法或帮助。
这段代码是从这个答案https://stackoverflow.com/a/21640840/6025994修改的
// the power set of [] is [[]]
if(arr.length === 0) {
return [[]];
}
// remove and remember the last element of the array
var lastElement = arr.pop();
// take the powerset of the rest of the array
var restPowerset = powerSet(arr);
// for each set in the power set of arr minus its last element,
// include that set in the powerset of arr both with and without
// the last element of arr
var powerset = [];
for(var i = 0, len = restPowerset.length; i < len; i++) {
var set = restPowerset[i];
// without last element
powerset.push(set);
// with last element
set = set.slice(); // create a new array that's a copy of set
set.push(lastElement);
powerset.push(set);
}
return powerset;
};
var subsetsLessThan = function (arr, number) {
// all subsets of arr
var powerset = powerSet(arr);
// subsets summing less than or equal to number
var subsets = new Set();
for(var i = 0, len = powerset.length; i < len; i++) {
var subset = powerset[i];
var sum = 0;
const newObject = {};
for(var j = 0, len2 = subset.length; j < len2; j++) {
if (newObject[subset[j].name]) {
newObject[subset[j].name]++;
} else {
newObject[subset[j].name] = 1;
}
sum += subset[j].seat;
}
const difference = number - sum;
newObject.ambulatory = difference;
if(sum <= number) {
subsets.add(JSON.stringify(newObject));
}
}
return [...subsets].map(subset => JSON.parse(subset));
};
const a = [{
name: 'grocery',
capacity: 2,
total: 5
}, {
name: 'wheelchair',
capacity: 0,
total: 3
}];
const hrStart = process.hrtime();
const array = [];
for (let i = 0, len = a.length; i < len; i++) {
for (let tot = 0, len2 = a[i].total; tot < len2; tot++) {
array.push({
name: a[i].name,
seat: a[i].capacity
});
}
}
const combinations = subsetsLessThan(array, 10);
const hrEnd = process.hrtime(hrStart);
// for (const combination of combinations) {
// console.log(combination);
// }
console.info('Execution time (hr): %ds %dms', hrEnd[0], hrEnd[1] / 1000000)
期望结果是传入的结果的所有组合小于车辆容量,因此它本质上是一个组合小于和算法。例如,我发布的代码的预期结果是 -->
[{"ambulatory":10},{"wheelchair":1,"ambulatory":10},{"wheelchair":2,"ambulatory":10},{"wheelchair":3,"ambulatory":10},{"grocery":1,"ambulatory":8},{"grocery":1,"wheelchair":1,"ambulatory":8},{"grocery":1,"wheelchair":2,"ambulatory":8},{"grocery":1,"wheelchair":3,"ambulatory":8},{"grocery":2,"ambulatory":6},{"grocery":2,"wheelchair":1,"ambulatory":6},{"grocery":2,"wheelchair":2,"ambulatory":6},{"grocery":2,"wheelchair":3,"ambulatory":6},{"grocery":3,"ambulatory":4},{"grocery":3,"wheelchair":1,"ambulatory":4},{"grocery":3,"wheelchair":2,"ambulatory":4},{"grocery":3,"wheelchair":3,"ambulatory":4},{"grocery":4,"ambulatory":2},{"grocery":4,"wheelchair":1,"ambulatory":2},{"grocery":4,"wheelchair":2,"ambulatory":2},{"grocery":4,"wheelchair":3,"ambulatory":2},{"grocery":5,"ambulatory":0},{"grocery":5,"wheelchair":1,"ambulatory":0},{"grocery":5,"wheelchair":2,"ambulatory":0},{"grocery":5,"wheelchair":3,"ambulatory":0}]
【问题讨论】:
-
为什么轮椅的容量是0?不应该是 1 吗?
-
该特定输入是指定轮椅区域的示例,例如在公共汽车上。当容量为 0 时,它不占用任何其他流动座位。
-
但是可以无限量添加它们为
0 * Infinity < 10? -
那是公平的,我忘了在我的问题中添加它,但是对象的总数使得这不可能。例如,此示例中的轮椅总数为 3,因此只能有 3 个。我已更新问题以反映该情况。
-
啊,好吧,但是你在计算之前删除了
total。我将编辑我的答案以反映这一点。
标签: javascript node.js algorithm combinations