zoukankan      html  css  js  c++  java
  • 292_Nim Game

    292_Nim Game

    一、题目详情

      题目的意思是给定石头的数量n,双方每次只能拿1-3个石头,己方先手,问在给定n后,自己能不能获胜。

    二、解题方法

    第一种方法(Time Limit Exceeded)

      一开始拿到题目,我的第一想法是使用博弈树的思想解题,当节点状态是己方行动&&石子数量<=3获胜,当节点是对方行动&&石子数量<=3失败。因为双方都足够聪明,所以要在对手每一步取走1个,2个,3个石子都必须取胜。代码如下:
    class Solution {
        public boolean canWinNim(int n) {
            return canWinNimHelper(n,true);
        }
        //isSelf==true表示己方行动,false表示对手行动
        public boolean canWinNimHelper(int n,boolean isSelf){
            if(n<=3&&isSelf) return true;
            if(n<=3&&!isSelf) return false;
            if(isSelf)
                return canWinNimHelper(n-1,!isSelf)
                    || canWinNimHelper(n-2,!isSelf)
                    || canWinNimHelper(n-3,!isSelf);
            else
                return canWinNimHelper(n-1,!isSelf)
                    && canWinNimHelper(n-2,!isSelf)
                    && canWinNimHelper(n-3,!isSelf);
        }
    }
    

      不出意料这种方法Time Limit Exceeded.

    第二种方法(Memory Limit Exceeded)

      因为上面这种算法超时,我观察了一下该算法,可以使用动态规划的思想解决超时问题。算法具体为:现在求得是由n个石子是否能赢,则只要拿走1个棋子或者两个棋子或者三个棋子后,对方会输就行(己方和对方是一样的,dp[i]只表示现在行动的那方能不能赢)。所以就有: dp[i] = !(dp[i-1]&&dp[i-2]&&dp[i-3])
    class Solution {
        public boolean canWinNim(int n) {
            if(n<=3) return true;
            boolean[] dp = new boolean[n+1];
            dp[1] = true;dp[2]=true;dp[3]=true;
            for(int i=4;i<=n;i++){
                dp[i] = !(dp[i-1]&&dp[i-2]&&dp[i-3]);
            }
            return dp[n];
        }
    }
    

      这个我以为可以accept,但是题目给的数据太大,建立dp数组太耗空间,但是这里可以改进一下:因为dp时只需要i的i-1,i-2,i-3的值,所以可以只保留这三个,这样就解决了内存的问题。

    第三种方法(Accept)

      这种方法比较特殊。只要n不能被4整除自己就能赢。 解释:我们可以知道当n=1,2,3时我们可以赢,当n=4时我们会输。当n=5,6,7时,我们可以对应的拿掉1,2,3个石子让对方行动时只有4个棋子,我们就能赢。n=8时,我们会输。以此类推,只要n不能被4整除自己就能赢。
    class Solution {
        public boolean canWinNim(int n) {
            return !(n%4==0);
        } 
    }
  • 相关阅读:
    Three.js入门和搭建HelloWorld
    CentOS中使用Docker来部署Tomcat
    CentOS中使用Docker来部署Nginx
    Windows中通过bat定时执行命令和mysqldump实现数据库备份
    Geoserver在Linux上的安装(图文教程)
    Linux上怎样停止服务(jar包)、查看进程路径、关闭指定端口
    Java中怎样监测局域网内ip是否互通,类似ping
    Android和JS之间互相调用方法并传递参数
    Android中使用WebView加载本地html并支持运行JS代码和支持缩放
    ARC072C
  • 原文地址:https://www.cnblogs.com/Mrfanl/p/11695378.html
Copyright © 2011-2022 走看看