给儿子买了一套数字华容道的棋盘,结果毫不意外地成了我打发时间的工具,玩儿多了后就有了一些心得,结合网上的资料,总结如下图所示。
这是一个NPC问题,目前还没有通用解法。更深刻的数学原理涉及到群论了,群论在大学数学里面有着完全不一样的画风,没有深入学习过。
分析:
列数为奇数时,空格的上下移动并不影响当前排列的逆向序数,以下三个排列的逆序数都是偶数。
列数为偶数时,由于上下移动空格一次是奇排列,会导致排列逆序数奇偶性变化,所以为了保证总的排列为偶排列,必须满足逆序数+空格行数为偶数。
其实总结起来,无论列数为奇数还是偶数,都需要满足如下公式:
数字逆序数+(空格行数 mod 2)*((阶数+1)mod 2)= 偶排列
若随机打乱数字(如将3×3拼图排为 [1,2,3],[4,5,6],[8,7,X]),
逆序数为奇数且空格在第三行(奇行),则不可解.
用此公式验证二阶华容道的六种合法状态,全部符合公式预测:
也就是必须满足空格在最后一行的时候,数字的逆序数为偶数,只是由于列数为奇数的时候,空格位置不影响数字排列奇偶性,所以这个要求能够在空格任意状态下满足,而当列数为偶数时,必须两个互相配合,才能达到这个要求。
计算逆序数的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
printf("请输入数字序列的长度:");
scanf("%d", &n);
int a[n];
printf("请输入%d个数字(用空格分隔):", n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
// 计算逆序数
int count = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (a[i] > a[j]) {
count++;
}
}
}
printf("逆序数为:%d\n", count);
printf("该排列是%s排列\n", count % 2 == 0 ? "偶" : "奇");
return 0;
}
以三阶为例,可以验证,每个复原步骤均满足上述条件:
共计48步,这个步数必定是个偶数,因为黑框从最后一个位置再回到最后的位置,必定为偶数,根据群的基本理论,所以必须保证初始状态的逆序数也为偶数。这样完成后才满足偶置换的要求,如上的所有条件都是为了满足这个要求
深搜程序,计算出来四种方案,步骤都非常多,可见如果想得到最优步数需要用到广搜,深搜一头走到黑,得到的一般不是最优结果,如果限制路径堆栈的深度,可以得到接近最优的搜索路径:
我们按照程序计算出来的顺序实际操作一遍:
up->left->left->up->right->right->down->left->left->up->right->right->down->left->left->up->right->right->down->down->left->up->up->right->down->left->down->right->up->up->left->down->left->up->right->right->down->down->left->up->left->down->right->up->right->down->left->up->right->down
按照程序给出的操作步骤,顺利完成了3阶华容道的还原。
程序在限定步数前后,搜索步数会出现较大差异,是由于深度搜索过程中,首次出现的某个可解状态并非以最优次序出现,导致即便后续最优序列出现的时候,由于状态重复而被剪枝。
限定最大不超过30步的情况下的搜索结果:
left->left->up->right->right->up->left->down->right->up->left->down->left->down->right->up->right->down->left->left->up->right->up->left->down->right->down->left->up->right->right->down
空格和空格行数
空格水平位置的变化不影响逆序数,但是垂直方向上的变化却可能影响逆序数的奇偶性变化,并且这种影响和华容道的阶数有关,对于三阶来说,空格上下移动,相当于数字向前/向后连续置换了两次,次数为偶数,所以逆序数仍然是偶数保持不变,可以不用考虑空格行数的变化。
但是对于四阶来说,上下移动后,相当于一个数字向前/向后移动了三个块,发生三次置换,次数为奇数,所以逆序数的奇偶性一定发生了变化,需要加上空格行数作为补偿。是偶数才能复原。
进一步引申,奇数阶的数字华容道是否有解,只和当前数字排列的奇偶性有关,逆序数为偶数才有解。偶数阶的数字华容道,除了要考虑数字排列逆序数之外,还需要考虑到空格所在的行数。
华容道的系统性解法
在人的置换面前,计算机的暴力破解显然算不上高明。华容道隐藏着一套精妙的复原密码,严谨的方法论便是解锁它的钥匙,针对华容道的复原,已然形成了一套完备的策略路径与操作范式,参考如下文章:
扩展
华容道问题很像一个迷宫问题,区别是迷宫问题会限制行走的边界,而对于数字华容道来说,空格是无形的存在,在边界范围内可以自由腾挪,只是这种任意腾挪是否能够遍历所有的LAYOUT,或者任意给定的有效LAYOUT,通过空格的任意变化能是否能够走到,不知道有没有理论上的证明。