取石子

简介:

Tang和Jiang非常喜欢玩一种有趣的小游戏: 有N个石子,两人轮流从中取出1个, 3个或4个石子,当石子被取空时,游戏结束。最后一个取石子的人获胜, 第一次总是Tang取. 当然,他们俩都足够聪明,总会采取最优的策略。
Input
每行会有一个正整数N(N<=100000), 代表石子的个数, N=0 代表输入结束
Output
输出获胜人的名字。
Sample Input
1 //石头数量为1
2
0
Sample Output
Tang //石头数量为1的时候,总是Tang会赢
Jiang

 

分治法: 穷举出所有可能的取石头方案                                             

算法思想,假设两个玩家分别pid编号为0和1。f(n, pid)表示当前一轮获胜的玩家编号(如果f=0,表示获胜玩家是0),其中n表示当前一轮的石头总数,pid表示当前一轮的玩家标号。

      考虑分治算法的思想,当前一轮的胜负结果取决于对下一轮各种情况的结果的统计。这个统计有两种情况:

      1、当前一轮玩家pid=0,那么他取石头的可能性为1,3或4。则下一轮玩家pid=1的情况有三种: f(n-1, 1),f(n-3,1),f(n-4,1)。如果这三种情况的f()函数值至少有一个是0,不妨假设f(n-1, 1)=0,根据题目条件的"他们俩都足够聪明,总会采取最优的策略。" ,那么当前一轮pid=0的玩家一定会选择取1个石头,结果也一定是pid=0赢。

           因此当pid=0时, f(n ,0)=f(n-1, 1)&f(n-3, 1)&f(n-4, 1)

      2、当前一轮玩家pid=1,那么下一轮三种情况下只要有一个f()函数值为1,则结果一定是pid=1赢。即

           当pid=1是, f(n ,1)=f(n-1, 0)|f(n-3, 0)|f(n-4, 0)

代码                                                                                   

复制代码
public class RecurStonePlay {  
    private static final String[] PLAYER={"Tang","Jiang"};  
    /** 
     * 当前轮到第pIdx个PLAYER从剩下的stoneNum块石头中取石头获胜的情况 
     * @param stoneNum 当前石头总数 
     * @param pIdx 取石头的人的ID 
     * @return 在当前这种情况下,能够取胜的PLAYER的ID 
     */  
    public static int turn(int stoneNum,int pIdx){  
          
        //当前只有1,3,4块石头时,则当前PLAYER[pIdx]能够取胜  
        if(stoneNum==1||stoneNum==3||stoneNum==4) return pIdx;  
        //当前只有2块石头时,则PLAYER[(pIdx+1)%2]能取胜  
        if(stoneNum==2) return (pIdx+1)%2;  
          
        //如果当前是PLAYER[0]取石头,则只要取1,3,4块三种情况中一种情况下能够取胜,则PLAYER[0]获胜。  
        //使用&运算,如果有一个0,则结果为0  
        if(pIdx==0)  
            return turn(stoneNum-1,(pIdx+1)%2)&turn(stoneNum-3,(pIdx+1)%2)&turn(stoneNum-4,(pIdx+1)%2);  
        //与上面情况相反,如果有一个1,则结果为1  
        else  
            return turn(stoneNum-1,(pIdx+1)%2)|turn(stoneNum-3,(pIdx+1)%2)|turn(stoneNum-4,(pIdx+1)%2);  
    }  
      
       //测试  
    public static void main(String[] args) {  
                //石头总数为5块,PLAYER[0]开始先玩  
        System.out.println(PLAYER[RecurStonePlay.turn(5,0)]);  
    }  
}
复制代码

分析                                                                                   

上面的方法时间复杂度太高,那么 是否能够通过对当前一轮石头总数的判断,可以知道是当前玩家赢(先手赢),还是下一轮的玩家赢(后手赢)呢? 

我们假设先手玩家是Player1,后手玩家是Player2。用上面的程序运行1-30个石头,并输出赢的情况(其中0代表Player1赢,1代表Player2赢)。

1  2   3  4  5  6  7  8  9   10   11  12  13  14  15   16  17  18   19  20  21  22  23  24  25  26  27   28  29  30

0  1   0  0  0  0  1   0  1    0    0    0    0    1    0    1     0    0    0    0    1     0    1     0    0    0    0      1     0    1

我们可以发现,凡是mod 7 余2或0的石头数目,都是后手赢,其他情况都是先手赢。 我们来证明一下:

(1) stoneNum=1,2,3,4时就不证明了。

(2) 当stoneNum=2的时候,是Player2赢。我们能够想到,如果Player1抽取石头后,能使得Player2玩的时候手头上的石头数量为2。那么Player1一定赢。也就是说(2+1=3),(2+3=5),(2+4=6)的石头数量一定导致Player1赢。

(3) 当stoneNum=7的时候,Player1无论抽1,3,4块石头中的任意情况,都会使得Player2玩的时候手头上的石头数量为6,4,3。这三种石头数量都是当前玩家赢(Player2赢)。因此7块石头一定是Player2赢。

(4) 当stoneNum=7的时候,情况与(2)相同。因此(7+1=8),(7+3=10),(7+4=11)的石头数量一定是Player1赢。

(5) 当stoneNum=9的时候,情况与(3)相同。因此9块石头一定是Player3赢。

(6) 依次下去,我们就能够得出这个结论:

策略:如果当前石头数量stoneNum%7==2||stoneNum%7==0,那么一定是后手赢。除此之外是先手赢。




本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3906100.html,如需转载请自行联系原作者

相关文章
|
2月前
|
人工智能 缓存 开发者
MCP协议究竟如何实现RAG与Agent的深度融合,打造更智能AI系统?
本文AI专家三桥君探讨了通过MCP协议实现RAG与Agent系统的深度融合,构建兼具知识理解与任务执行能力的智能系统。文章分析了传统RAG和Agent系统的局限性,提出了MCP协议的核心设计,包括标准化接口、智能缓存和动态扩展性。系统架构基于LlamaIndex和LangGraph实现服务端和客户端的协同工作,并提供了实际应用场景与生产部署指南。未来发展方向包括多模态扩展、增量更新和分布式处理等。
270 0
基于STM32F10X的BMP280程序
基于STM32F10X的BMP280程序
|
机器学习/深度学习 人工智能 安全
回望现阶段人工智能招聘岗位和条件
【7月更文挑战第4天】AI公司招聘涉及多个机器学习角色:所有职位都强调尖端ML技术和对用户体验的改进。
556 4
回望现阶段人工智能招聘岗位和条件
|
对象存储 数据库
2025年 | 9月云大使推广奖励规则
云大使推广返利活动,企业新用户下单返佣加码5%,推广最高返佣45%,新老用户都可参与返利活动。
|
Java 数据库连接 数据库
你还在用分页?试试 MyBatis 流式查询,真心强大!
流式查询 指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。
|
2天前
|
人工智能 运维 安全
|
5天前
|
SpringCloudAlibaba 负载均衡 Dubbo
微服务架构下Feign和Dubbo的性能大比拼,到底鹿死谁手?
本文对比分析了SpringCloudAlibaba框架下Feign与Dubbo的服务调用性能及差异。Feign基于HTTP协议,使用简单,适合轻量级微服务架构;Dubbo采用RPC通信,性能更优,支持丰富的服务治理功能。通过实际测试,Dubbo在调用性能、负载均衡和服务发现方面表现更出色。两者各有适用场景,可根据项目需求灵活选择。
386 124
微服务架构下Feign和Dubbo的性能大比拼,到底鹿死谁手?
|
7天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
702 107