现在,要枚举集合
中的所有k = 4组合Set = [1; 2; 3; 4; 5; 6; 7; 8]
我使用预先构建的Matlab函数nchoosek来计算二项式系数。一次取k个n个事物的组合数由n!/((n-k)!k!)计算。
现在,假设我有一组包含n = 8个元素的数据:
Set = [1.A; 2.B; 3.C; 4.D; 5.B; 6.D; 7.C; 8.A]
我想在“Set”中枚举4 整数的所有组合,但有一个转折:我必须只有一个元素具有相同的字母任意组合(顺序无关紧要)。例如:
[1.A; 2.B; 6.D; 7.C]是一个有效的组合,但不是[1.A; 2.B; 6.D; 8.A。
有[1.A; 2.B; 6.D; 7.C],我仍然必须产生组合[8.A; 2.B; 6.D; 7.C]
不必生成70种组合,因为有2次出现的A,B,C和D,我只需要生成2 * 2 * 2 * 2 = 16种组合。 70-16 = 54个其他组合与我的问题无关,我宁愿不生成它们,因为它变得越来越计算扩展。目前,我生成了70种组合,然后使用一些逻辑来删除所有不相关的组合。
所以,我的问题是:
答案 0 :(得分:2)
将您设置转换为表单
[A[1, 8], B[2,5], C[3,7], D[4,6]]
通过字母键生成基本组合 - 这里只有一个(C(4,4))基本组合(A,B,C,D)并使用数字子键扩展组合(例如,使用递归方法)
答案 1 :(得分:1)
您的扭曲会对问题产生约束。据我所知,这个新问题没有特别的名称,它只是一个与其他问题一样的组合问题。
请注意,您最终做的是为每个可能的"插槽"添加选项。在结果集中。常规选择公式的基本假设是给定项目可以在集合中,也可以不在集合中。请注意,对于每个组A,B,C和D,要么
OR
因此,在结果集中选择哪些类型整数就类似于选择原始问题的结果集中的实际整数!一旦我们选择了结果集中的哪些类型的整数,我们就可以选择将每种类型的整数放入集合中。
在你的情况下,如果我们必须选择4种类型进入集合,那么这样做的方式是4选择4 = 1(A,B,C,D)。对于类型A有2个选项,类型B有2个选项,类型C有2个选项,类型D有2个选项,所以有2 * 2 * 2 * 2 = 16组可供选择:)
答案 2 :(得分:1)
这只是具有单一性检查的标准C(N,K)。下面的代码是JavaScript,但将其转换为C ++应该不会太困难。
function nchoosekUnique(arr, k, combo, result) {
if(combo.length === k) {
result.push(combo);
return result;
}
for(var i=0; i < arr.length - k; i++) {
// UNIQUE CHECK
var unique = true;
for(var u=0; u<combo.length; u++) {
if(combo[u][1] == arr[i][1]) {
unique = false;
continue;
}
}
//
if(unique === true) {
var comboCpy = combo.slice(0);
var arrCpy = arr.slice(0);
comboCpy[comboCpy.length] = arrCpy.splice(i, 1)[0];
nchoosekUnique(arrCpy, k, comboCpy, result);
}
}
return result;
}
var arr = [[1,"A"], [2,"B"], [3,"C"], [4,"D"], [5,"B"], [6,"D"], [7,"C"], [8,"A"]];
JSON.stringify(nchoosekUnique(arr, 4, [], []), null, '\t');
注意如果您的K非常大,您可能希望对combo变量使用Set(HashSet)实现而不仅仅是数组。
答案 3 :(得分:1)
一般递归(迭代迭代,如果堆叠)算法:
combs(index,multiset,k,result):
if length of result == k:
output result
return
if length of result + length of multiset - index < k:
return
for j in multiset[index]:
combs(index + 1,multiset,k,result with multiset[index][j] added)
combs(index + 1,multiset,k,result)
JavaScript示例:
function combs(i,multiset,k,result){
if (result.length == k){
console.log(result);
return;
}
if (result.length + multiset.length - i < k)
return;
for (var j=0; j<multiset[i].length; j++){
_result = result.slice();
_result.push(multiset[i][j]);
combs(i + 1,multiset,k,_result);
}
combs(i + 1,multiset,k,result);
}
combs(0,[["1.A","8.A"],["2.B","5.B"],["3.C","7.C"],["4.D","6.D"]],4,[]);