zoukankan      html  css  js  c++  java
  • hdu 1907(Nim博弈)

    John

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 4407    Accepted Submission(s): 2520


    Problem Description
    Little John is playing very funny game with his younger brother. There is one big box filled with M&Ms of different colors. At first John has to eat several M&Ms of the same color. Then his opponent has to make a turn. And so on. Please note that each player has to eat at least one M&M during his turn. If John (or his brother) will eat the last M&M from the box he will be considered as a looser and he will have to buy a new candy box.

    Both of players are using optimal game strategy. John starts first always. You will be given information about M&Ms and your task is to determine a winner of such a beautiful game.

     
    Input
    The first line of input will contain a single integer T – the number of test cases. Next T pairs of lines will describe tests in a following format. The first line of each test will contain an integer N – the amount of different M&M colors in a box. Next line will contain N integers Ai, separated by spaces – amount of M&Ms of i-th color.

    Constraints:
    1 <= T <= 474,
    1 <= N <= 47,
    1 <= Ai <= 4747

     
    Output
    Output T lines each of them containing information about game winner. Print “John” if John will win the game or “Brother” in other case.

     
    Sample Input
    2 3 3 5 1 1 1
     
    Sample Output
    John Brother
     
    题意:在n堆中取糖吃,每次可以在其中的一堆中取至少一个,谁取完所有的糖果就输了,问最后谁会赢?
    此游戏可以简化为nim博弈模型:
    今有若干堆火柴,两人依次从中拿取,规定每次只能从一堆中取若干根, 可将一堆全取走,但不可不取,最后取完者为负,求必胜的方法。
    解法:定义:若所有火柴数异或为0,则该状态被称为利他态,用字母T表示;否则, 为利己态,用S表示。
    定义:T态中,若充裕堆的堆数大于等于2,则称为完全利他态,用T2表示;若充裕堆的堆数等于0,则称为部分利他态,用T0表示。
    [定理5]:S0态,即仅有奇数个孤单堆,必败。T0态必胜。
    [定理6]:S1态,只要方法正确,必胜。
    中间过程不再赘述:
    结论:
    必输态有:  T2,S0 
    必胜态:    S2,S1,T0.
     
    所以这题求出John的必输态即可.
    #include <iostream>
    #include <cstring>
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    
    int main()
    {
        int tcase;
        scanf("%d",&tcase);
        while(tcase--){
            int n,sum = 0,v,_cnt=0,_cnt1=0; ///_cnt 代表孤单堆的数量,_cnt1 代表充裕堆的数量
            scanf("%d",&n);
            for(int i=0;i<n;i++){
                scanf("%d",&v);
                if(v==1) _cnt++;
                if(v>1) _cnt1++;
                sum^=v;
            }
            if(_cnt%2&&_cnt1==0||_cnt1>=2&&sum==0){
                printf("Brother
    ");
            }else{
                printf("John
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    挖地雷——线性dp
    hdu6376 度度熊剪纸条-----01背包
    Problem
    UVa 10635
    Vjudge_题目分享_A -> 线性Dp排列木棍 ( Dilworth定理应用
    洛谷日报 & 原来博客(转载)
    使用.net6 WebApplication打造最小API
    k8s笔记——NodePort暴露nginx-controller实现https自动跳转自定义nodePort端口
    通过Dapr实现一个简单的基于.net的微服务电商系统(十七)——服务保护之动态配置与热重载
    通过Dapr实现一个简单的基于.net的微服务电商系统(十六)——dapr+sentinel中间件实现服务保护
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5768285.html
Copyright © 2011-2022 走看看