zoukankan      html  css  js  c++  java
  • [BZOJ 1874] [BeiJing2009 WinterCamp] 取石子游戏 【博弈论 | SG函数】

    题目链接:BZOJ - 1874

    题目分析

    这个是一种组合游戏,是许多单个SG游戏的和。

    就是指,总的游戏由许多单个SG游戏组合而成,每个SG游戏(也就是每一堆石子)之间互不干扰,每次从所有的单个游戏中选一个进行决策,如果所有单个游戏都无法决策,游戏失败。

    有一个结论,SG(A + B + C ... ) = SG(A)^SG(B)^SG(C) ...

    这道题每堆石子不超过 1000 , 所以可以把 [0, 1000] 的 SG 值暴力求出来,使用最原始的 SG 函数的定义, SG(u) = mex(SG(v))           E(u -> v) 。

    注意 m <= 10 所以一个状态 i 的后继状态不超过 10 个,那么它的 SG 值不会超过 10 。

    然后将每一堆的 SG 值异或起来。如果必胜,就按照顺序枚举一下所有初始方案,找到必胜的就输出并退出。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
     
    using namespace std;
     
    const int MaxNum = 1000 + 5, MaxN = 10 + 5;
     
    int n, m, Mark_Index;
    int A[MaxN], B[MaxN], SG[MaxNum], Mark[MaxN];
     
    void Calc_SG() {
        SG[0] = 0;
        Mark_Index = 0;
        memset(Mark, 0, sizeof(Mark));
        for (int i = 1; i <= 1000; ++i) {
            ++Mark_Index;
            for (int j = 1; j <= m; ++j) {
                if (B[j] > i) continue;
                Mark[SG[i - B[j]]] = Mark_Index;
            }
            for (int j = 0; j <= 10; ++j) {
                if (Mark[j] != Mark_Index) {
                    SG[i] = j;
                    break;
                }
            }
        }
    }
     
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i) scanf("%d", &B[i]);
        Calc_SG();
        int Temp = 0;
        for (int i = 1; i <= n; ++i) Temp ^= SG[A[i]];
        if (Temp == 0) printf("NO
    ");
        else {
            printf("YES
    ");
            bool Flag = false;
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= m; ++j) {
                    if (B[j] > A[i]) continue;
                    if ((Temp ^ SG[A[i]] ^ SG[A[i] - B[j]]) == 0) {
                        Flag = true;
                        printf("%d %d
    ", i, B[j]);
                        break;
                    }
                }
                if (Flag) break;
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    [luogu2059 JLOI2013] 卡牌游戏 (概率dp)
    [luogu1772 ZJOI2006] 物流运输 (最短路 线性dp)
    [luogu 2568] GCD (欧拉函数)
    [poj 2976] Dropping tests (分数规划 二分)
    cf掉分记——Avito Code Challenge 2018
    新博客的第一篇博文~
    [noip2011 luogu1312] Mayan游戏(模拟)
    bzoj2618 [Cqoi2006]凸多边形
    LLppdd never give up!
    我的scoi2018
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4257030.html
Copyright © 2011-2022 走看看