最简单的方法似乎是回溯方法。您可以跟踪您用平面阵列看到的5位序列。在每一位,尝试加入0 - counter = (counter & 0x0f) << 1
并检查您是否曾经看过,然后执行counter = counter | 1
并尝试该路径。
可能有更高效的算法可以更快地修剪搜索空间。这似乎与https://en.wikipedia.org/wiki/De_Bruijn_sequence有关。我不确定,但我相信它实际上是相同的;也就是说,序列的最后五位数字必须为10000
,使其成为循环。
编辑:这里有一些c代码。由于递归,空间效率低于它,但很简单。最糟糕的是掩模管理。看来我对De Bruijn序列是正确的;这发现了所有2048个。
#include <stdio.h>
#include <stdlib.h>
char *binprint(int val) {
static char res[33];
int i;
res[32] = 0;
for (i = 0; i < 32; i++) {
res[31 - i] = (val & 1) + '0';
val = val >> 1;
}
return res;
}
void checkPoint(int mask, int counter) {
// Get the appropriate bit in the mask
int idxmask = 1 << (counter & 0x1f);
// Abort if we've seen this suffix before
if (mask & idxmask) {
return;
}
// Update the mask
mask = mask | idxmask;
// We're done if we've hit all 32
if (mask == 0xffffffff) {
printf("%10u 0000%s\n", counter, binprint(counter));
return;
}
checkPoint(mask, counter << 1);
checkPoint(mask, (counter << 1) | 1);
}
void main(int argc, char *argv[]) {
checkPoint(0, 0);
}
这是一个非常好的解决方案。我花了一些时间来了解你的方法,所以我会添加一些评论来帮助别人。上面提到的“平面阵列”由32个5位子序列组成。因此,这可以有效地用一个32位的位域来表示,这就是'mask'变量。也就是说,一旦5位值被放入“计数器”(例如,“01101”)的5个最右边位中,则相应的位(例如'13')被设置在“掩码”中。这就是你如何跟踪重复('if(mask&idxmask)return;')和完成时间('if(mask == 0xffffffff)')。 – Matt 2015-04-03 20:52:15