版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://www.blogbus.com/yjq24-logs/42653430.html
上次说了胜态和必败态,还记得最后的练习么?桌子上有15个石子,每人每次可以拿去1个或3个石子,拿走最后一个石子的人赢,列出所有的必败态:0,2,4,6,8,10,12,14。说过了状态作为结点可以画一张有向图,下面这张图就是这个游戏所对应的:
定理:有限个结点的无回路有向图有唯一的核。
证明:核可以用如下的方式找出:首先找出没有后继结点的点集P[1](最基本的必败态,比如上图中的结点0),然后找到那些指向P[1]的结点集合为N[1](最基本的胜态,比如上图的结点1和结点3);然后,除去P[1]和N[1]中的点并除去和这些点关联的边,继续寻找没有后继结点的点集P[2](更高级的必败态,比如上图中的结点2),依次类推,则最后的核为P=P[1]并P[2]并…并P[n]。
很容易说明如此找到的核是内固集,也是外固集,满足核的定义,下面说明一下核为什么不是空集:实际上P[1]就不是空集,对一个没有回路的有向图来说,从图上的某一点出发,就无法回到原来到过的点。而图中的点又是有限的,所以最后必将在某个结点终止,故P不是空集。
针对不同的游戏,找核是一个麻烦事。首先生成图,有向边取决于游戏规则,然后当我们要找某个必败态的时候,是要先找到之前所有的必败态的,而这正是一个数学问题和一个编程问题的关键差别。在立方和分解问题[unsolved]中,我的问题的提法都是针对某一个特定输入的n来看是否存在(x,y)满足立方和或者平方和等于n.实际上,如果提法换成,输出对所有不大于n的数中可以被分解的数,那么这种提法更适合计算机去解决,因为本质上来说,两个问题是不一样的。对于前者我只需要知道有关n的情况就可以了,而对后者,却调动了资源去计算所有不大于n的数的情况。虽然他们看起来很相近,但是从道理上来说应该后者的劳动量要大得多,可悲的事情就在于,有时候你要算出n的情况,就不得不算一些比n小的数的情况,而这个计算的数目通常是随着n增大而增大的;另一个可悲的事情是,程序员往往已经习惯了第二种提问方式。数学家希望找到某些必要条件或者充分条件来确定n能否被分解,同样的道理,我们也希望能直接找到必败态的规律,而不真正依赖于象上述定理那样递归的思想从P[1]开始找起,这样来解决问题。
但是,必败态的规律是严格依赖于规则的,这一点对找出必败态的规律来说造成了很大的局限性。这个图的模型在以后还会遇到,到时有更好的方法来寻找必败态。