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);
        } 
    }
  • 相关阅读:
    Zepto swipe 无效(坑)
    Zepto.js-Ajax 请求
    Zepto.js-事件处理
    excel 大文件解析原理实现
    springboot 集成J2Cache
    springboot 单元测试 指定启动类
    springboot 解决 数字长度过长导致JS精度丢失问题
    JS 基本操作
    VUE 动态菜单管理
    VUE router-view key 属性解释
  • 原文地址:https://www.cnblogs.com/Mrfanl/p/11695378.html
Copyright © 2011-2022 走看看