【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 }

 

posted @ 2018-05-07 11:39  程序员博博  阅读(1636)  评论(0编辑  收藏  举报