编程之美读书笔记之1.11~1.13 一排石头的游戏

1.11 要求是N块石头排成一排,位置固定,A和B每次取任意一块或者相邻两块,最后取光者获胜;使用对称策略,先取者B先取中间的一个(奇数个)或者两个(偶数个),然后取跟A对称的位置相同的个数的石头即可。先取者获胜;

扩展问题1:条件不变,最后取光者输。根据石头的个数分析:1输,2赢,3赢,4输,5赢,6赢,接下来分析就比较麻烦了,未解决。。。

扩展问题2:一堆石头,每人每次最多取1块,最多取K块,根据石头个数确定输赢;

若有1~k块,先取者B赢;

若k+1块,B输;

若有k+2~2(k+1)块,B赢,通过第一次取石头,将石头剩余个数变为k+1,A必输;

同理,若有n(k+1)块石头,只有A保证每次取的个数为(k+1)-B上次取的块数,即两次取的块数总和为k+1,B必输;若有n(k+1)+m,0<m<k+1,B必赢;

*1.12 要求是N堆,每次从一堆中取若干个石头,最后取光者获胜。使用异或方法求解,通过分析1堆、2堆((1,1),(k,k))、n堆(1,1,1…1),若初始每堆个数的异或结果为0,则先取者必输;要求A每次取后能保证异或结果始终为0;可通过一次循环,求得前n-1个较小数的异或结果,再将最大数变为此结果求解;

扩展问题1:取光者输;分析如上,异或结果非0,先取者B必输,A必胜(保证每次异或结果非0);异或结果为0,先取者必胜;

扩展问题2:每次从若干堆中取若干个石头;,???

1.13 要求是2堆,每次从两堆石头中取相等的石头,或者仅从一堆中取任意个石头,最后取光者获胜。固定获胜集合。根据题目的提示,(1,2)先取者必输,考虑到2-1=1,所有满足(k+1,k+2)(k>0),(1,k)(此处k≠2),(2,k)(此处k>1)的情况先取者都能获胜。然后分析差值为2的情况,首先想到的是(3,5),此处没有用到之前的数字1、2,分析可知先取者必输,同理分析差值为3且跟之前数字不重复的情况为(4,7),以此类推,能够获得必输集合中所有元素。

扩展问题1:要求给出获胜的中间取石头的方法。若开始情况不是必输状态,则通过一次取数,使得当前状态为必输状态,方法为若初始为(n,m)(n<m),查询必输集合有(n,m1),若m1<m,则取m-m1个,是当前状态变为(n,m1);若m1>m,计算m-n,查询必须集合中两数差值为m-n的元素(n2,m2),然后n和m分别减去(n-n2)即可(此时n-n2=m-m2)。

扩展问题2:一堆石头,第一个人不能拿光所有石头,第一次之后每人每次最多拿对方前一次取石头数目的2倍。

分析:n=1,不合理;

n=2=1+1,必输;

n=3=1+2,必输;

n=4=1+2+1,必赢;

n=5=1+f(4),必输;

n=6=1+f(5),比赢;

规律,先取者第一次取数为≤(n-1)/3;跟斐波那契数列类似,f(n)=i+f(n-i),其中0<i≤(n-1)/3;若存在f(n-i)=false,则f(n)=true;

实现代码为:

bool Solute(int n)
{
    if(n==1 || n==2 || n==3){
        return false;
    }

    for(int i=1 ; i<=(n-1)/3 ; i++){//note
        if(Solute(n-i) == false){
            return true;
        }
    }
    return false;
}

    原文作者:littlekenan
    原文地址: https://blog.csdn.net/littlekenan/article/details/22103785
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞