- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试编写一种算法,根据不同的输入组合将车辆“装满”至其容量。问题已解决,但速度太慢,无法用于更多组合。
例如:我有一辆容量为 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, “门诊”:10},{“杂货店”:1,“门诊”:8},{“杂货店”:1,“轮椅”:1,“门诊”:8},{“杂货店”:1,“轮椅” ":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,“门诊”:4},{“杂货店”:3,“轮椅”:3,“门诊”:4},{“杂货店”:4,“门诊”:2},{“杂货店”:4, “轮椅”:1,“门诊”:2},{“杂货店”:4,“轮椅”:2,“门诊”:2},{“杂货店”:4,“轮椅”:3,“门诊”: 2},{"grocery":5,"ambulatory":0},{"grocery":5,"wheelchair":1,"ambulatory":0},{"grocery":5,"wheelchair":2, "ambulatory":0},{"grocery":5,"wheelchair":3,"ambulatory":0}]
最佳答案
您可以使用一种技巧来改进您的算法,称为 backtracking :如果你到达一条不可能的路,例如5 -> 6,那你就不用继续找了,因为5+6已经大于10了,这样可以消去很多组合。
function* combineMax([current, ...rest], max, previous = {}) {
// Base Case: if there are no items left to place, end the recursion here
if(!current) {
// If the maximum is reached exactly, then this a valid solution, yield it up
if(!max) yield previous;
return;
}
// if the "max" left is e.g. 8, then the grocery with "seat" being 2 can only fit in 4 times at max, therefore loop from 0 to 4
for(let amount = 0; (!current.seat || amount <= max / current.seat) && amount <= current.total; amount++) {
// The recursive call
yield* combineMax(
rest, // exclude the current item as that was used already
max - amount * current.seat, // e.g. max was 10, we take "seat: 2" 3 times, then the max left is "10 - 2 * 3"
{ ...previous, [current.name]: amount } // add the current amount
);
}
}
const result = [...combineMax([
{ name: 'grocery', seat: 2, total: Infinity },
{ name: 'wheelchair', seat: 0, total: 3 },
{ name: 'ambulatory equipment', seat: 1, total: Infinity },
//...
], 10)];
关于javascript - 我想找到最有效的方式来填充车辆,基本上是满足车辆容量的不同组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56703395/
这是我的预期输出 我试图在不裁剪图像的情况下获得输出,这是我的代码 .blog-col-group { display: flex; } .blog-col {} .mod-vin-img {
这是我的预期输出 我试图在不裁剪图像的情况下获得输出,这是我的代码 .blog-col-group { display: flex; } .blog-col {} .mod-vin-img {
我正在编写一个 C++ 程序,该程序采用包含 double 的真实输入信号的 FFT。值并返回一个 vector X包含 std::complex值。获得结果 vector 后,我会尝试计算结果的幅度
A B C D 1 3 3 3 3 3 结果很明显,自然加入后 A B C D 1 3 3 3 3 3 3 3 这是为什么?我认为自然连接要求在这两种情况下具有相似的属性?第一张表连C、D属
对于我的网站,我通过 jquery 将所有子页面加载到一个 div 中,该 div 基本上涵盖了除菜单之外的所有内容。结构是这样的,你按下帐户按钮,你会得到登录表单,然后有一个链接(触发一个 oncl
我从 GPUImage 中的边缘检测滤镜得到了一张黑白图像,其中白色代表边缘,图像内容大部分是黑色的,不透明的。问题是,我想将此图像叠加在另一个图像之上,以显示边缘如何与下面的图像对齐。 但是非边缘区
好的,我的数据库类有一个数据库项目。我有一个用 MySQL 制作的数据库,正在用 C# 制作我的应用程序。该数据库基本上只是一个部件数据库,在 4NF 中由部件、关系表、构建、客户和订单表组成,因为这
我在 scipy 中使用 griddata 函数来插入 3 维和 4 维数据。它像冠军一样工作,除了它返回一堆 NaN,因为我需要的一些点超出了输入数据的范围。考虑到 N-d 数据无论如何仅适用于“线
我正在 Linux (Ubuntu) 上编写一个 C++ 程序。我想删除一个目录的内容。它可以是松散的文件或子目录。 本质上,我想做一些等同于的事情 rm -rf /* 您能否建议在 C++ 中执行此
我使用node.js加密文件并在JAVA中解密。解密是使用“AES/GCM/Nopadding”算法在 JAVA 中完成的,它是第三方应用程序,因此我无法更改 JAVA 代码。我使用“aes-256-
我是一名优秀的程序员,十分优秀!