• [BZOJ 1115] [POI2009] 石子游戏Kam 【阶梯博弈】


    题目链接:BZOJ - 1115

    题目分析

    首先看一下阶梯博弈:

    阶梯博弈是指:初始有 n 堆石子,每次可以从任意的第 i 堆拿若干石子放到第 i - 1 堆。最终不能操作的人失败。 

    解法:将奇数位的石子堆做最基本的 NIM 就可以了。

    WHY:对奇数位做 NIM 的必胜者总是可以胜利,因为如果从奇数位拿石子到偶数位,就相当于把这些石子拿走了,就是 NIM ;如果必败者从偶数位将石子拿到奇数位,必胜者总是可以将这些石子再向前移一个位置,就又放到了偶数位,这样一直移动的话,最终会是必胜者将这些石子拿到了 0 位置,然后必败者就不能再移动这些石子了。就相当于没有发生变化,偶数位的石子对我们的游戏就相当于没有影响。 

    然后看一下这道题,要求保证总是满足单调不降。

    我们对石子进行差分,即 B[i] = A[i] - A[i - 1]。那么就会发现,从第 i 堆拿走一颗石子就是相当于将 B[i] -= 1, B[i + 1] += 1,那么就是一个向后进行的阶梯 NIM 了,从后向前取奇数位的 Bi 异或一下就可以了。 

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int MaxN = 1000 + 5;
    
    int T, n;
    int A[MaxN], B[MaxN];
    
    int main()
    {
    	scanf("%d", &T);
    	for (int Case = 1; Case <= T; ++Case)
    	{
    		scanf("%d", &n);
    		for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
    		for (int i = 1; i <= n; ++i) B[i] = A[i] - A[i - 1];
    		int Temp = 0;
    		for (int i = n; i > 0; i -= 2) Temp ^= B[i];
    		if (Temp) printf("TAK
    ");
    		else printf("NIE
    ");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    10.矩形覆盖 Java
    09.变态跳台阶 Java
    08.青蛙跳台阶 Java
    07.斐波那契数列 Java
    06.旋转数组的最小数字 Java
    05.用两个栈实现队列 Java
    04.重建二叉树 (Java)
    03.从尾到头打印链表 (Java)
    数据结构-有序链表的合并
    数据结构-判断链表是否存在环形链表
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4350577.html
Copyright © 2020-2023  润新知