• UVA12293 Box Game —— SG博弈


    题目链接:https://vjudge.net/problem/UVA-12293

    题意:

    两人玩游戏,有两个盒子,开始时第一个盒子装了n个球, 第二个盒子装了一个球。每次操作都将刷量少的盒子的球倒掉,然后再从数量多的盒子中拿出若干个球放到空盒子里,最终状态为(1,1),达到这个状态的玩家获胜。

    题解:

    1.由于每次都是倒掉数量少的那个盒子,再对数量多的盒子进行分割,所以可以把规则简化为:初始时有n个球,每次只能拿走不多于n/2的球,最终状态为1个球,达到这个状态的玩家获胜。

    2.简化游戏规则之后,可知这是一个典型的SG博弈,但是由于n的范围很大,不能直接求SG值,那就打表找规律,如下:

    可知,当n为 2^i - 1时,先手输;否则先手赢。

    代码一:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 100+10;
    18 
    19 int SG[MAXN], vis[MAXN];
    20 void table()
    21 {
    22     SG[1] = 0;
    23     for(int i = 2; i<=35; i++)
    24     {
    25         memset(vis, 0, sizeof(vis));
    26         for(int j = (i+1)/2; j<i; j++) vis[SG[j]] = 1;
    27         for(int j = 0;;j++) if(!vis[j]) {
    28             SG[i] = j;
    29             break;
    30         }
    31     }
    32     for(int i = 1; i<=32; i++) printf("%-2d ",i); putchar('
    ');
    33     for(int i = 1; i<=32; i++) printf("%-2d ",SG[i]); putchar('
    ');
    34 /*
    35     1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    36     0  1  0  2  1  3  0  4  2  5  1  6  3  7  0  8  4  9  2  10 5  11 1  12 6  13 3  14 7  15 0  16
    37 */
    38 }
    39 
    40 bool judge(int x)
    41 {
    42     x++;
    43     int bit = 0;
    44     while(x)
    45     {
    46         bit += x&1;
    47         x >>= 1;
    48     }
    49     return bit==1;
    50 }
    51 
    52 
    53 int main()
    54 {
    55 //    table();
    56     int n;
    57     while(scanf("%d", &n) &&n)
    58     {
    59         if(judge(n)) printf("Bob
    ");
    60         else printf("Alice
    ");
    61     }
    62 }
    View Code

    代码二:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 100+10;
    18 
    19 int SG[MAXN], vis[MAXN];
    20 void table()
    21 {
    22     SG[1] = 0;
    23     for(int i = 2; i<=32; i++)
    24     {
    25         memset(vis, 0, sizeof(vis));
    26         for(int j = (i+1)/2; j<i; j++) vis[SG[j]] = 1;
    27         for(int j = 0;;j++) if(!vis[j]) {
    28             SG[i] = j;
    29             break;
    30         }
    31     }
    32     for(int i = 1; i<=32; i++) printf("%-2d ",i); putchar('
    ');
    33     for(int i = 1; i<=32; i++) printf("%-2d ",SG[i]); putchar('
    ');
    34 /*
    35     1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    36     0  1  0  2  1  3  0  4  2  5  1  6  3  7  0  8  4  9  2  10 5  11 1  12 6  13 3  14 7  15 0  16
    37 */
    38 }
    39 
    40 int main()
    41 {
    42 //    table();
    43     int n;
    44     while(scanf("%d", &n) &&n)
    45     {
    46         if(n&(n+1)) printf("Alice
    ");
    47         else printf("Bob
    ");
    48     }
    49 }
    View Code
  • 相关阅读:
    0121 集合类 ArrayList 的练习
    0121 有关接口的使用练习
    泛型相关知识
    0120 父类与子类创建、重写及转型练习
    0118练习 单例模式
    java设计模式 略版
    0117 面向对象OOP有关方法、类、构造方法及权限修饰符的练习
    0115 创建类并调用
    [luogu P2586] GCD 解题报告 (莫比乌斯反演|欧拉函数)
    POJ1284 Primitive Roots (原根)
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8342051.html
Copyright © 2020-2023  润新知