【发布时间】:2015-07-30 13:51:37
【问题描述】:
这是我之前的 question 关于寻找下一位排列的内容。我突然想到我必须修改我的代码以实现类似于下一位排列的东西,但完全不同。
我正在以 int 的位表示形式编码有关图中顶点邻居的信息。例如,如果n = 4(n - 图顶点)并且图已满,我的顶点数组如下所示:
vertices[0]=14 // 1110 - it means vertex no. 1 is connected with vertices no. 2, 3, and 4
vertices[1]=13 // 1101 - it means vertex no. 2 is connected with vertices no. 1, 3, and 4
vertices[2]=11 // 1011 - it means vertex no. 3 is connected with vertices no. 1, 2, and 4
vertices[3]=7 // 0111 - it means vertex no. 4 is connected with vertices no. 1, 2, and 3
第一个(主)for 循环是从 0 到 2^n(因为 2^n 是集合的子集数)。
所以如果n = 4,那么就有16个子集:
{empty}, {1}, ..., {4}, {0,1}, {0,2}, ..., {3,4}, {0,1,2}, ..., {1,2,3}, {1,2,3,4}
这些子集由for循环中的索引值表示
for(int i=0; i < 2^n; ++i) // i - represents value of subset
假设是n = 4,实际上是i = 5 //0101。我想检查这个子集的子集,所以我想检查:
0000
0001
0100
0101
现在我正在生成 1 位集合的所有位排列,然后是 2 位集合的排列......等等(直到我达到 BitCount(5) = 2)并且我只采用我想要的排列(通过 if 语句)。不需要的计算太多了。
所以我的问题是,如何生成所有可能的组合而不重复 (n,k) 其中 n - 图形顶点和 k - i (stated above) 中的位数
我的实际代码(生成所有位排列并选择错误):
for (int i = 0; i < PowerNumber; i++)
{
int independentSetsSum = 0;
int bc = BitCount(i);
if(bc == 1) independentSetsSum = 1;
else if (bc > 1)
{
for(int j = 1; j <= bc; ++j)
{
unsigned int v = (1 << j) - 1; // current permutation of bits
int bc2 = BitCount(j);
while(v <= i)
{
if((i & v) == v)
for(int neigh = 1; neigh <= bc2; neigh++)
if((v & vertices[GetBitPositionByNr(v, neigh) - 1]) == 0)
independentSetsSum ++;
unsigned int t = (v | (v - 1)) + 1;
v = t | ((((t & -t) / (v & -v)) >> 1) - 1);
}
}
}
}
所有这一切都是因为我必须计算 n 的每个子集的独立集合数。
编辑
我想在不创建任何数组的情况下执行此操作,或者通常我想避免分配任何内存(既不是向量)。
一点解释:
n=5 //00101 - it is bit count of a number i - stated above,k=3,集合中的数字(数字代表位位置设置为1)
{
1, // 0000001
2, // 0000010
4, // 0001000
6, // 0100000
7 // 1000000
}
所以正确的组合是{1,2,6} // 0100011,但{1,3,6} // 0100101 是错误的组合。在我的代码中有很多错误的组合需要过滤。
【问题讨论】:
-
你需要按位运算的效率吗?如果不是这样,您可以通过抽象一点来省去很多麻烦(wrt 操纵图表)。
-
我的目标是编写最有效的函数,所以如果可能的话 - 我想像在我的代码中那样使用按位运算。
标签: c++ algorithm graph bit-manipulation combinations