zoukankan      html  css  js  c++  java
  • Nim游戏变种——取纽扣谁先取完

    (2017腾讯实习生校招笔试题)Calvin和David正在玩取纽扣游戏,桌上一共有16个纽扣,两人轮流来取纽扣,每人每次可以选择取1个或3个或6个(不允许不取),谁取完最后的纽扣谁赢。Cavin和David都非常想赢得这个游戏,如果Cavin可以先取,Cavin的必胜策略下第一步应该取 
      A、1个 
      B、3个 
      C、6个 
      D、Cavin没有必胜策略

      解析:这道题是Nim游戏的变种,Nim游戏是博弈论中最经典的模型(之一)。

      根据博弈论的性质:对于巴什博弈,存在必胜点必败点,是指在当前这个点上的先手玩家是“必胜”(指的是采取必胜策略下的必胜)还是必败。对于一个点,如果它的下一步全是必胜点,那么显然无论它如何走都是让对手进入必胜点,所以当前这个点就是必败点;如果下一步中存在一个必败点,那么当前这一步的玩家就可以选择让对手进入这个必败点的走法,所以当前这个点就是是必胜点

      对这题来说,显然0的时候是必败点;看1,只能选择拿走1个,变成0,0是必败点,1可以到达必败点,所以1是必胜点;然后看2,2的下一步只能选择拿走1个变成1,1是必胜点,2只能到达必胜点,所以2是必败点;3的下一步2和0,都是必败点,3可以到达必败点,所以3是必胜点.......同理,当推到16的时候,下一步有三种走法,分别是15,13,10,由前面推理过程,15和10都是必胜点,只有13是必败点。因此先手应该选择拿走3个棋子,让对手进入必败点。

      详细推理过程如下表(自上而下):

    必败点 必胜点
    0  
      1
    2  
      3
    4  
      5
      6
      7
      8
    9  
      10
    11  
      12
    13  
      14
      15
      16
    import java.util.HashSet;
    import java.util.Scanner;
    import java.util.Set;
    
    /**
     * Created by dave on 2016/9/1.
     * 假设有16个球,有david和cavin两个人轮流来取,每个人只能去1,3,6.先取完的为胜。由David先取,问David第一次去多少才能保证胜利
     */
    public class Main {
        static int[] steps = new int[]{1,3,6};
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int count = scanner.nextInt();
            int choose = doWork(count);
            System.out.println(choose);
        }
        private static int doWork(int count){
            Set<Integer> allowSet = new HashSet<>();
            Set<Integer> failSet = new HashSet<>();
    
            for(int tmp:steps)
                allowSet.add(tmp);
    
            for(int i = 1;i<count;i++){
                if(allowSet.contains(i))
                    continue;
                if(checkIsAllowed(failSet,i))
                    allowSet.add(i);
                else if(checkIsFailed(allowSet,i))
                    failSet.add(i);
            }
    
            for(int tmp:steps){
                if(failSet.contains(count-tmp))
                    return tmp;
            }
            return -1;
        }
    
        private static boolean checkIsAllowed(Set<Integer> set,int val){
            for(int tmp:steps){
                tmp = val-tmp;
                if(tmp > 0 && set.contains(tmp))//下一步是对面必败点,该点是必胜点
                    return true;
            }
            return false;
        }
        private static boolean checkIsFailed(Set<Integer> set,int val){
            for(int tmp:steps){
                tmp = val-tmp;
                if(tmp > 0 && !set.contains(tmp))//下一步不在必胜点中
                   return false;
            }
            return true;//下一步在必胜点,该点必败
        }
    }

    Nim游戏变种——取纽扣游戏

    腾讯模拟题之取球问题

  • 相关阅读:
    js 数组的length(javascript教程四)
    js利用数组length属性清空和截短数组
    mysql一对多关联查询的时候筛选条件
    PHP错误处理及异常处理笔记
    Javascript获取URL地址变量参数值的方法
    php 提示Warning: mysql_fetch_array() expects
    Centos中安装PHP的PDO MySQL扩展的教程
    ASP.NET缓存 Cache之数据缓存
    Spring.Net框架一:Spring.Net简介
    T4模板
  • 原文地址:https://www.cnblogs.com/34fj/p/9342118.html
Copyright © 2011-2022 走看看