我不确定这里的技术术语是什么,所以我可以搜索一个术语。
比方说,一个角色有多个权重不同的决定。
Decision A: 1
Decision B: 3
Decision C: 5
Sum: 9
代码的作用是将它们加在一起,这样决策A的几率为1/9,决策B的几率为3/9,决策C的几率为5/9。
有些因素会从池中删除并添加某些决定。这些权重不是固定的(例如,对于更聪明的字符,B可以为2,或者使用各自的权重分为B1和B2)。
现在我正在做的只是线性搜索,如下所示(在JavaScript中):
let totalWeight = 0;
for (let i = array.length - 1; i >= 0; i--) {
totalWeight += array[i].weight;
}
// this function rolls a random number from 1 to totalWeight
let r = roll(1, totalWeight);
let search = 1;
for (let i = 0; i < array.length; i++) {
let w = array[i].weight;
if (r >= search && r < (search+w)){
return array[i];
}
search += w;
}
但这似乎不是很有效。看起来这里可以有一个二进制搜索算法,但我似乎想不到。有什么想法吗?
答案 0 :(得分:2)
如果权重每轮变化,并且不同轮之间既没有共性,又没有不变性,那么我认为没有一种算法可以大大胜过线性扫描。
Here是执行此任务的算法的列表。
答案 1 :(得分:2)
在查看了您键入的代码之后,我认为技术/算法rejection sampling
是您要寻找的技术/算法。要使用拒绝采样获得相同的代码输出,请执行以下操作:
var sample = [];
for (let i = array.length - 1; i >= 0; i--) {
for(let j = array[i].weight-1;j>=0;j--) {
sample.push(i);
}
}
// this function rolls a random number from 0 to sample.length-1
// which sample.length should be equivalent to your total weight
let r = roll(0, sample.length-1);
return array[sample[r]];
上面的代码减少了时间复杂度,但增加了空间复杂度。
如果您尝试在不使用binary search
的算法中实现rejection sampling
,请尝试以下代码:
let totalWeight = 0;
//add one property into your array, call it accumulative_weight or aw
for (let i = array.length - 1; i >= 0; i--) {
totalWeight += array[i].weight;
//assign the accumulative_weight property
array.aw = totalWeight;
}
// this function rolls a random number from 1 to totalWeight
let r = roll(1, totalWeight);
let start = 0;
let end = array.length;
let position = "not found";
while(start!=end)
{
let target = parseInt((end-start)/2);
if( array[target].aw > r )
end = target;
else if ( array[target].aw - array[target].weight < r )
start = target;
else
{
let position = target;
break;
}
}
return position;
请注意,您的数组必须排序。希望能帮助到你。