假设我想枚举所有4位模式,即来自0 (0000) to 15 (1111)
。一种方法是"真值表"的方法:
0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, ... 1111
这种方法相当于以十进制从0到15进行计数。
另一种方法是使用格雷码,其中一次只翻转一位:
0000, 0001, 0011, 0010, 0110, ... 1000
我如何系统地枚举最小化位总和的顺序中的所有数字?例如,类似于:
0000, 0001, 0010, 0100, 1000, 0011, 0101, 1001, 0110, 1010, 1001, 0111, 1011, 1101, 1110, 1111
表示4位示例。
最终,将它扩展到任何基础都会很好,但二元情况似乎是最直接的实现。
编辑:我可能应该明确表示该方法必须是生成性的,即我不能计算所有可能的序列,然后对它们进行排序;解决方案必须按照与指定顺序相似的顺序迭代生成序列。
答案 0 :(得分:1)
这个笨拙的黑客
unsigned next_combination(unsigned x)
{
unsigned u = x & -x;
unsigned v = u + x;
x = v + (((v ^ x) / u) >> 2);
return x;
}
将允许您轻松枚举按递增顺序包含相同数量的1位的所有unsigned
位组合。 (见https://en.wikipedia.org/wiki/Combinatorial_number_system)
您可以使用此算法按顺序枚举所有组合,包括一个1位,两个1位,三个1位,依此类推。例如,对于最多4位长的组合(如您的示例所示)
#define N 4u
int main()
{
for (unsigned k = 1; k <= N; ++k)
{
for (unsigned subset = (1 << k) - 1;
subset < (1 << N);
subset = next_combination(subset))
printf("%X ", subset);
printf("\n");
}
}
http://coliru.stacked-crooked.com/a/0c8327c5e0611eaa
上面的维基百科链接还包含更多通用算法的描述,而不是依赖于任何比特麻烦。
答案 1 :(得分:0)
int main()
{
int n, p, j, i = 0, sum;
cin >> n;
bool *wsk = new bool[n];
int hmany = static_cast<int> (pow(2, n));
bool **sortarr = new bool *[hmany];
for (int i = 0; i < hmany; i++) sortarr[i] = new bool[n];
bool *wsk1 = wsk;
for (int i = 0; i < n; i++) *wsk++ = 0;
wsk = wsk1;
int z = 0;
int c = n - 1;
do
{
sum = 0;
c = n - 1;
for (int i = 0; i < n; i++)
{
if (wsk[i] == 1) sum += static_cast<int>(pow(2,c));
c--;
}
z = sum;
for (int i = 0; i < n; i++)
{
sortarr[z][i] = wsk[i];
}
z++; wsk = wsk1;
i++; p = 0; j = i;
while (j % 2 == 0)
{
j /= 2; p++;
}
if (p <= n) wsk[p] = ((1 - wsk[p]) != 0);
} while (p < n);
这就是你想要的一切。
答案 2 :(得分:0)
这将转储二进制值列表,按设置的二进制数字(总体)计数,升序排序。根据序数值对人口相等的数字进行排名。
使用每个唯一的4位整数填充int
值数组。
std :: sort对数组进行排序,使用lambda来比较值。 lambda调用函数population
来获取数字的设置位数。
然后,列表由函数dump_array
输出,它将整数值转换为std::bitset
,以便在发送到std :: cout时获得二进制表示。
#include <iostream>
#include <array>
#include <algorithm>
#include <bitset>
template <typename T>
int population(T x) { // x<0 => oo loop
int count = 0;
while(x) {
count += x & 1;
x >>= 1;
}
return count;
}
template <typename A>
void dump_array(const A& a) {
const char* delim = "";
for(auto v : a) {
std::bitset<4> bits(v);
std::cout << delim << bits;
delim = ", ";
}
std::cout << '\n';
}
int main() {
std::array<int, 1<<4> vals;
int i=0;
for(auto& v : vals) { v = i++; }
std::sort(vals.begin(), vals.end(), [](int a, int b) {
const int pop_a = population(a);
const int pop_b = population(b);
return pop_a < pop_b || (pop_a == pop_b && a < b);
});
dump_array(vals);
}