C++ 如何解决可能的唯一组合问题
我需要一个大数的组合算法。我在StackOverflow上发现了一些东西,但实现并不完全正确。如果向量的大小大于22-24且k更大,则下面的代码将运行错误C++ 如何解决可能的唯一组合问题,c++,performance,combinations,C++,Performance,Combinations,我需要一个大数的组合算法。我在StackOverflow上发现了一些东西,但实现并不完全正确。如果向量的大小大于22-24且k更大,则下面的代码将运行错误 #包括 使用名称空间std; 模板 无效打印(常量T&c、整数组合) { int n=c.size(); 对于(int i=0;i>i)&1) CUT< P>之所以失败,是因为你发布的原始算法是利用了一些比特计算,它实际上是把一个 int 类型的每个位看作不同的数字,并且根据编译器定义的 int ,你可以被限制为32或64的最大值 n>代码
#包括
使用名称空间std;
模板
无效打印(常量T&c、整数组合)
{
int n=c.size();
对于(int i=0;i>i)&1)
CUT< P>之所以失败,是因为你发布的原始算法是利用了一些比特计算,它实际上是把一个<代码> int <代码>类型的每个位看作不同的数字,并且根据编译器定义的<代码> int <代码>,你可以被限制为32或64的最大值<代码> n>代码>。d还将所有int
声明更改为int64\t
,以强制将它们定义为64位
但是,这样做仍然会将最大n
限制为64。(事实上,它被限制为位大小-2
或62
或30
,因此不能完全确定为什么会被限制在23左右)真正的解决方案是将所有int
更改为std::bitset
,这样它就可以存储SIZE\u MAX
的最大n
- 代码如下:
#包括
#包括
#包括
模板
void pretty_print(常量std::vector&c,std::位集组合)
{
int n=c.size();
对于(int i=0;i>i)&std::bitset(1))!=std::bitset(0))
什么是“大数组合算法”?例如有一个向量{30,30,30,30,30,30,30,60,60,60,60,60,60,90,90,90,90,90,90},当你试图用8来求这个向量的组合时,它做得不正确。我也认为位计算可能是错误的,但我不擅长按位运算。我不太理解while循环。你能准确地描述“大数组合算法”是什么吗?这对我来说意味着什么“用8求这个向量的组合“?据我所知,您希望获得n
-元素集的所有不同k
-元素子集。一种方法是使用int之类的基元类型并使用位移位。另一种方法是使用位集。但两种方法都必须避免重复。另一种方法是将元素重新构造为无序映射{30:8,60:8,90:8}
并存储向量中的元素数:{0,0,8}
。使用这些元素创建所有置换。然后将向量增加到{0,1,7}
并创建所有排列。最后你将得到所有可能的组合。没有重复。@ThomasSablik-hmm你说的最后一种方法可能很好。我认为它可以用来编码。首先谢谢,我还在为项目的UI使用QT,也许在QT中可以有一些数据类型。但是,该程序在最后将是32位的部署。顺便说一下,我不知道是谁投的票。因为我是新来的,所以我不能vote@BilalCan我已经更新了我的代码,但是它们的运行速度并没有那么快,因为我不擅长实现逐位计算。另外,如果只处理nCk,链接中的其他方法也不会那么慢≈ 5000,除非你想找到n的解决方案≈ 5000您的代码产生重复:OP要求唯一的组合。@ThomasSablik您是对的,但我试图解决主要问题,他发现如果n
大于某个值,代码将无法运行amount@Ranoiaetep您的代码有一个问题。位集需要编译时常量表达式,但我的ve的大小ctor实际上在运行时发生了变化。因此编译器给出了错误。根据输入,我应该编写const int n=degree_list_loop.size(),在您的算法中,我不能这样做,因为它是运行时表达式。
#include <iostream>
#include <vector>
#include <bitset>
template<size_t bitSize>
void pretty_print(const std::vector<std::bitset<bitSize>>& c, std::bitset<bitSize> combo)
{
int n = c.size();
for (int i = 0; i < n; ++i) {
if (((combo >> i) & std::bitset < bitSize>(1)) != std::bitset <bitSize>(0))
std::cout << c[i].to_ullong() << ' ';
}
std::cout << std::endl;
}
template<size_t bitSize>
bool smallerThan(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
for (size_t i = bitSize - 1; i > 0; i--)
{
if (bits1[i] < bits2[i])
{
return true;
}
}
return false;
}
template<size_t bitSize>
std::bitset<bitSize> bitAddition(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
std::bitset<bitSize> carry;
while (bits2 != std::bitset<bitSize>(0))
{
carry = bits1 & bits2;
bits1 = bits1 ^ bits2;
bits2 = carry << 1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitSubtraction(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
while (bits2 != std::bitset<bitSize>(0))
{
std::bitset<bitSize> borrow = (~bits1) & bits2;
bits1 = bits1 ^ bits2;
bits2 = borrow << 1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitSubtractionStopAt0(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
while (bits2 != std::bitset<bitSize>(0))
{
std::bitset<bitSize> borrow = (~bits1) & bits2;
bits1 = bits1 ^ bits2;
bits2 = borrow << 1;
if (bits1 == std::bitset<bitSize>(0)) return bits1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitDivision(std::bitset<bitSize> dividend, std::bitset<bitSize> divisor)
{
std::bitset<bitSize> quotient(0);
while (smallerThan(std::bitset<bitSize>(0), dividend))
{
dividend = bitSubtractionStopAt0(dividend, divisor);
quotient = bitAddition(quotient, std::bitset<bitSize>(1));
}
return quotient;
}
template<size_t bitSize>
void combo(const std::vector<std::bitset<bitSize>>& c, int k)
{
auto n = c.size();
std::bitset<bitSize> one(1);
std::bitset<bitSize> combo(bitSubtraction((one << k), std::bitset<bitSize>(1)));
while (smallerThan(combo, (one << n)))
{
pretty_print(c, combo);
auto negCombo = combo;
negCombo.flip();
for (size_t i = 0; i < bitSize; i++)
{
negCombo.flip(i);
if (negCombo[i])
{
break;
}
}
std::bitset<bitSize> x = combo & negCombo;
std::bitset<bitSize> y;
bool tempBit = 0;
for (size_t i = 0; i < bitSize; i++)
{
y[i] = combo[i] ^ x[i];
if (tempBit)
{
if (!y[i])
{
tempBit = 0;
}
y[i] = y[i] ^ 1;
}
if (combo[i] & x[i])
{
tempBit = 1;
}
}
std::bitset<bitSize> z = (combo & ~y);
combo = bitDivision(z, x);
combo >>= 1;
combo |= y;
}
}
int main()
{
const int n = 500;
int k = 2;
std::bitset<(n + 2)> n_bits(n);
std::vector<std::bitset<n + 2>> people;
for (unsigned long i = 1; i < n_bits.to_ullong() + 1; ++i) { people.push_back(i); }
combo(people, k);
return 0;
}