青草游戏-简单易懂

参考地址

题目

牛牛和羊羊都很喜欢青草。今天他们决定玩青草游戏。最初有一个装有n份青草的箱子,牛牛和羊羊依次进行,牛牛先开始。在每个回合中,每个玩家必须吃一些箱子中的青草,所吃的青草份数必须是4的x次幂,比如1,4,16,64等等。不能在箱子中吃到有效份数青草的玩家落败。假定牛牛和羊羊都是按照最佳方法进行游戏,请输出胜利者的名字。

输入描述:

输入包括t+1行。 第一行包括一个整数t(1 ≤ t ≤ 100),表示情况数. 接下来t行每行一个n(1 ≤ n ≤ 10^9),表示青草份数

输出描述:

对于每一个n,如果牛牛胜利输出"niu", 如果羊羊胜利输出"yang"。

示例1

输入

3 1 2 3

输出

niu yang niu

思路分析:

  • 这个题目,输入int,输出boolean,很容易想到找规律。

可是应该怎么找规律呢,我们可以先用暴力解法,然后直观地看结果是否满足某种规律

  • 暴力解法:运用递归的解决决策树,先算出前几个作为递归结束的条件。

1,3,4时牛赢,0,2,5时羊赢

  • 然后,牛选一个数(迭代:4的次幂),再把决策交给羊(羊来调用函数)

如果,羊的递归调用中只要有一次是输,说明牛可以赢

  • 同理,来到羊决策时,选一个数,把决策权交给牛。。。。
  • 查看输出结果

  • 找到规律:后先后先先,五个一轮回

怎么保证,这个规律在大于50仍然适用呢?

我么只设置了前5个的值,这样算出来,在大于16甚至大于32都是满足这个规律。

那么大胆推测,在大于64时也会满足这样的规律

易错点

  1. 在暴力解法中要注意到base会不会溢出,因为n已经接近2^9,如果再乘以4,有可能会超出int的范围。

难点:

  1. 不要去钻牛角尖,认为这种解法是旁门左道

代码展示

暴力解法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;



public class Main{
    public static String winner(int num){
        if(num<5){
            return (num==0||num==2)?"后手":"先手";
        }
        int base = 1;
        while(base<num){
            if(winner(num-base).equals("后手")){//所有博弈情况中,能否找到一种胜出的解。如果能,就用这个解
                return "先手";
            }
            if(base*4>num){//防止溢出
                break;
            }
            base = base*4;
        }
        return "后手";
    }
    
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());//10^9用int就足够
        for(int i = 0;i<50;i++){
            System.out.println(i+"份青草时: "+ winner(i));
        }
        
    }
}

正儿八经解法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main{

    
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());//10**9用int就足够
        
        int grass[] = new int[n];
            
        for(int i=0;i<n;i++){
            String str = br.readLine();
            grass[i] = Integer.parseInt(str);
        }
        
        for(int i=0;i<n;i++){
            grass[i] = grass[i]%5;
            System.out.println((grass[i]==0||grass[i]==2)?"yang":"niu");
        }
        

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值