码迷,mamicode.com
首页 > 其他好文 > 详细

从NIM问题说起

时间:2014-09-04 13:17:29      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   ar   strong   2014   

巴什博奕(BashGame):一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个,最后取光者得胜;
显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。

威佐夫博奕(WythoffGame):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。这也就是本书中提到的NIM问题;

结论:记两堆物品数量<a,b>;第n组不安全局面<a(n),b(n)>满足:a(n)+n=b(n) and a(n)=min(N-A(N-1)并B(n-1));其中N:所有正整数,A(n)={a1,.....a(n)},B(n)={b1.....b(n)};

那么可以直接根据上述结论求解,初始值:a1=1,b1=2,对给定数量的两堆物品,判断是否满足不安全局面,满足,先取者必败,否则先取者有胜利机会;算法复杂度O(N);

当然还有O(1)的公式可以解决问题:a(n) = [(1 + sqrt(5)) / 2 * n], b(n) = [(3 + sqrt(5)) / 2 * n];我们可以使用一个通项公式计算出所有不安全局面;

问题中必输态具有的性质:对于必输数对(a,b),假定a < b,具有两个性质,1.任何一个自然数在数对中都仅出现一次,任意一个b-a的差值也只出现一次,同时知道第n个点对的差值是n;

关于证明及后续处理可以参考这篇博文;

维基百科NIM参考

还有一个相似问题:桌子上有N堆硬币,数量为a1,a2,······an;两个玩家每次可以从任意一堆中取走任意个硬币(>0),最后将硬币取光的玩家胜;

结论:它是先摸者必输当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算;

相关证明可参考这篇博文;

关于异或运算:

a=a^b^b

可以使用这一位运算性质进行交换操作;

bubuko.com,布布扣
 1 struct RESULT
 2 {
 3     int a,b;
 4 };
 5 
 6 void swap(RESULT &num)
 7 {
 8     num.a=num.a^num.b;
 9     num.b=num.a^num.b;
10     num.a=num.a^num.b;
11 }
12 
13 int main( )
14 {
15     RESULT tmp;
16     tmp.a=1;
17     tmp.b=2;
18     swap(tmp);
19     cout<<tmp.a<<ends<<tmp.b<<endl;
20     return 0;
21 }
View Code

从NIM问题说起

标签:style   blog   http   color   os   使用   ar   strong   2014   

原文地址:http://www.cnblogs.com/chengyuz/p/3949231.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!