zoukankan      html  css  js  c++  java
  • 【Leetcode】292. Nim游戏

    题目链接:https://leetcode-cn.com/problems/nim-game/description/

    您和您的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 到 3 块石头。 拿掉最后一块石头的人就是胜利者。由您来开局。

    你们两个都是聪明人,相信都有最佳的游戏策略。 请编写一个函数,来判断您是否可以在给定的石头数量的情况下赢得游戏。

    比方说,如果堆中有4块石头,那么你永远不会赢得比赛:无论你拿走的是 1块,2块 还是 3块 石头,最后一块石头总是会被你的朋友拿走。

    这里做一个抽象,假设一推里面有n个石头,每次可以取 1-m 个石头。

    显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。这里我们就有一个想法了,假设这个石头推为 (m+1)的倍数,那么第一个人取k( 1 <= k <= m)个,只要第二个人取 (m+1-k)个石头,那么必定状态能回到最初的状态,m+1个。因为每个人都是很聪明的,取的石头的个数一定要对自己有利。那么,假设最初石头推不为 (m+1)的倍数。n=(m+1)r+s,那么第一个人只要取s个石头必定能获得胜利,反之,如果s == 0 ,那么第一个人必输。

    即,若n=k*(m+1),则后取着胜,反之,存在先取者获胜的取法。n%(m+1)==0. 先取者必败。

    AC代码:

    1 public boolean canWinNim(int n) {
    2 
    3     return (n % 4) == 0 ? false : true;
    4 }

    (扩展):尼姆博弈

    题型

    尼姆博弈模型,大致上是这样的:

    有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜。

    获胜情况对先取者的讨论

    异或结果为0,先取者必败,无获胜方法。后取者获胜;

    结果不为0,先取者有获胜的取法。

    拓展

    任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),取最后一颗石子的人获胜,问先取的人如何获胜?

    根据上面所述,N个数异或即可。如果开始的时候T=0,那么先取者必败,如果开始的时候T>0,那么只要每次取出石子使得T=0,即先取者有获胜的方法。

    最后一个奇异局势是(0,0...,0)。另一个奇异局势是(n,n,0...0),只要对手总是和我拿走一样多的物品,最后会面对(0,0...,0)。

    SG函数模板:

     1 import java.util.Arrays;
     2 
     3 class Main {
     4     // N 表示可以取的个数
     5     // MAXN表示每堆石头的最大数
     6     public static final int N = 20;
     7     public static final int MAXN = 1000;
     8     public static int[] f = new int[N];
     9     public static int[] SG = new int[MAXN + 10];
    10     public static int[] S = new int[MAXN + 10];
    11     
    12     public static void main(String[] args) {
    13         
    14         
    15     }
    16     
    17     void getSg(int n) {
    18         int i, j;
    19         Arrays.fill(SG, 0);
    20         for (i = 1; i <= n; i++) {
    21             Arrays.fill(S, 0);
    22             for (j = 0; f[j] <= i && j < N; j++)
    23                 S[SG[i - f[j]]] = 1;
    24             for (j = 0;; j++)
    25                 if (S[j] == 0) {
    26                     SG[i] = j;
    27                     break;
    28                 }
    29         }
    30     }
    31 }
     1 /*
     2 按照卡中心校园招聘的要求,HR小招和小商需要从三个科室中(分别为A、B、C)抽派面试官去往不同城市。
     3 两名HR按照以下规定轮流从任一科室选择面试官:每次至少选择一位,至多选择该科室剩余面试官数。最先选不到面试官的HR需要自己出差。
     4 假设HR小招和小商都不想出差且每次选择都采取最优策略,如果是小招先选,写一个函数来判断她是否需要出差。如果不需要出差,请给出第一步的最优策略。
     5 */
     6 // 测试用例 2,0,4 -> c,2   1,8,9 -> 1(需要出差)
     7 public class Main{
     8     public static void main(String[] args) {
     9         Scanner in = new Scanner(System.in);
    10         String string = in.next().toString();
    11         String stringArray[] = string.split(",");
    12         int num[] = new int[stringArray.length];
    13         for (int i = 0; i < stringArray.length; i++) {
    14             num[i] = Integer.parseInt(stringArray[i]);
    15         }
    16         int a = num[0];
    17         int b = num[1];
    18         int c = num[2];
    19         int bool = a ^ b ^ c;
    20         if (bool == 0)
    21             System.out.print(1);
    22         else {
    23             if ((a ^ b) < c) {
    24                 System.out.print("C," + (c - (a ^ b)));
    25             }
    26             if ((a ^ c) < b) {
    27                 System.out.print("B," + (b - (a ^ c)));
    28             }
    29             if ((b ^ c) < a) {
    30                 System.out.print("A," + (a -(b ^ c)));
    31             }
    32         }
    33     }
    34 }
  • 相关阅读:
    java.io.file
    连线小游戏
    发票类型区分的正则表达式(仅区分普票专票)
    mybatis: No enum constant org.apache.ibatis.type.JdbcType."VARCHAR"
    bootstrap inputfile 使用-上传,回显
    微积分极限中一例
    oracle 查看表结构语句
    redis无法连接
    项目配置shiro原缓存注解失效
    bug 找不到或无法加载主类main.java.*
  • 原文地址:https://www.cnblogs.com/wenbochang/p/9001833.html
Copyright © 2011-2022 走看看