答复
贴一下我的解法,标准递归,很容易理解:
/**
* 算法思路是: 依次使 9,8,7,...,1 位变成 0. 因为,假如使第 9 位变成 0 了,
* 那么再把第 8 位变成 0 时就不需要考虑第 9 位了. 同样,第 8 位变成 0 后,
* 再改变第 7 位时就不需要考虑 8,9 位. 问题难度将逐步降低,直到最终解决,
* 而且,这个思路可以递归实现.
*/
for (i = 9; i; i--)
{
if ( bits[i] != 0 )
{
xor(bits,i);
}
}
下面是 xor 函数实现:
/**
* 将 bits数组的第 pos 位取反,也就是 bits[pos] ^= 1.
*
* 为将 pos 位取反,必须先:
* 1. bits[pos - 1] = 1
* 2. bits[1] 到 bits[pos - 2] 都为 0
* 这个函数通过递归调用来满足这两个条件.
*
* @note 未做递归深度检查. CrackMe2 中序列号最长 4096 (就是前面定义的 MAX_TIMES),这里假设不会超过这个值.
*/
static void xor(uint8_t bits[10],int pos)
{
int i;
/// 递归结束条件
if (pos == 1)
{
bits[1] ^= 1;
m_codes[m_count++] = 1;
return;
}
/// 先递归调用来满足条件 1
if ( bits[pos - 1] == 0 )
{
xor(bits,pos - 1);
}
/// 再递归调用来满足条件2
for (i = pos - 2; i; i--)
{
if ( bits[i] != 0 )
{
xor(bits,i);
}
}
/// 2 个条件满足了,现在可以将第 pos 位取反了
bits[pos] ^= 1;
/// 记录第几步改变了第几位,后面根据这个生成序列号
m_codes[m_count++] = pos;
}
