Andy 胡

导航

2016蓝桥杯"取球博弈"问题

较难,网上有能得出正确结果的代码,但是读了一下,像是拼凑出的结果,逻辑不通,代码和注释不符

参考网上代码写了一版,结构相对清晰,注释比较详细

题目很长:

两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。

假设双方都采用最聪明的取法,第一个取球的人一定能赢吗?试编程解决这个问题。

输入格式:
第一行3个正整数n1 n2 n3,空格分开,表示每次可取的数目 (0<n1,n2,n3<100)
第二行5个正整数x1 x2 ... x5,空格分开,表示5局的初始球数(0<xi<1000)

输出格式:
一行5个字符,空格分开。分别表示每局先取球的人能否获胜。
能获胜则输出+,
次之,如有办法逼平对手,输出0,
无论如何都会输,则输出-

例如,输入:
1 2 3
1 2 3 4 5
程序应该输出:
+ 0 + 0 -

再例如,输入:
1 4 5
10 11 12 13 15
程序应该输出:
0 - 0 + +

再例如,输入:
2 3 5
7 8 9 10 11
程序应该输出:
+ 0 0 0 0

package ah;
import java.util.Arrays;
import java.util.Scanner;
// 输入3个数,表示可取球的数目{n1,n2,n3}
// 输入5局总球数{x1 x2 ... x5}
// 持有奇数个球的一方获胜
// 输出:先取球者的结果(+:能赢 0:能平 -:必输)
// ------------------------
// 输入:
// 1 2 3
// 1 2 3 4 5
// 输出:
// + 0 + 0 -
// ------------------------
// 输入:
// 1 4 5
// 10 11 12 13 15
// 输出:
// 0 - 0 + +
// ------------------------
// 输入:
// 2 3 5
// 7 8 9 10 11
// 输出:
// + 0 0 0 0
public class 取球博弈 {
    // 持有奇数个球的一方获胜
    static boolean isOdd(int num) {
        return num % 2 == 1 ? true : false;
    }
    // (+:能赢 0:能平 -:必输)
    static void showRersult(int _1的球, int _2的球) {
        String RET_WIN_ = "+ ";
        String RET_LOSE = "- ";
        String RET_TIE_ = "0 ";
        if (isOdd(_1的球) && !isOdd(_2的球)) {
            System.out.print(RET_WIN_);
        } else if (!isOdd(_1的球) && isOdd(_2的球)) {
            System.out.print(RET_LOSE);
        } else if (isOdd(_1的球) && isOdd(_2的球)) {
            System.out.print(RET_TIE_);
        } else {
            System.out.print(RET_TIE_);
        }
    }
    // 不够取:false
    // 够取:true
    static boolean isNotEnough(int _剩下的球, int _要取得球) {
        if (_剩下的球 < _要取得球) {
            return true;
        } else {
            return false;
        }
    }
    static void getInput() {
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < 3; i++) {
            _arr_n[i] = sc.nextInt();
        }
        for (int i = 0; i < 5; i++) {
            _arr_x[i] = sc.nextInt();
        }
        sc.close();
    }
    // java中方法参数传递方式是按值传递
    // 基本类型:传递的是基本类型的字面量值的拷贝
    // 引用类型:传递的是该参量所引用的对象在堆中地址值的拷贝
    // 所以参数[_取到的球数]在方法内的修改,方法外是得不到的,必须使用返回值
    public static int getBall(int i_N, int _取到的球数) {
        boolean _getted = false;
        for (int j = _arr_n.length - 1; j >= 0; j--) {
            // 取球,往多了取,如可取{1,2,3},先取3
            boolean b奇奇得偶 = (isOdd(_取到的球数) && isOdd(_arr_n[j]));
            boolean b偶偶得偶 = (!isOdd(_取到的球数) && !isOdd(_arr_n[j]));
            if (b奇奇得偶 || b偶偶得偶) {
                // 已经有奇数,还取奇数?不行(取了不就偶数了么?)
                // 已经有偶数,还取偶数?不行(取了不就偶数了么?)
                continue;
            }
            if (isNotEnough(_arr_x[i_N], _arr_n[j])) {
                // 剩余的球<可取的最小数:结束
                continue;
            }
            _取到的球数 += _arr_n[j];
            _arr_x[i_N] -= _arr_n[j];
            _getted = true;
            break;
        }
        if (!_getted) {
            // 如果上述方法没有取到, 取出一个最大的数
            for (int j = _arr_n.length - 1; j >= 0; j--) {
                if (isNotEnough(_arr_x[i_N], _arr_n[j])) {
                    continue;
                }
                _取到的球数 += _arr_n[j];
                _arr_x[i_N] -= _arr_n[j];
            }
        }
        return _取到的球数;
    }
    // 取球博弈(ball game playing)
    static void ballGamePlaying() {
        // 输入{取法}和{初始球数}
        // {可取}按升序排列
        Arrays.sort(_arr_n);
        // 计算每一局
        for (int i_N = 0; i_N < _arr_x.length; i_N++) {
            int _1的球 = 0, _2的球 = 0;
            while (true) {
                if (isNotEnough(_arr_x[i_N], _arr_n[0])) {
                    // 剩余的球<可取的最小数:结束
                    break;
                }
                _1的球 = getBall(i_N, _1的球);
                _2的球 = getBall(i_N, _2的球);
            }
            // 一局结束,输出结果
            showRersult(_1的球, _2的球);
        }
    }
    // 能取球数:可取球的数目{n1,n2,n3}
    static int[] _arr_n = new int[3];
    // 每一局的初始球数:输入5局总球数{x1 x2 ... x5}
    static int[] _arr_x = new int[5];
    public static void main(String[] args) {
        testCase123();
        ballGamePlaying();
        System.out.println();
        System.out.println("+ 0 + 0 -:标准答案");
        testCase145();
        ballGamePlaying();
        System.out.println();
        System.out.println("0 - 0 + +:标准答案");
        testCase235();
        ballGamePlaying();
        System.out.println();
        System.out.println("+ 0 0 0 0:标准答案");
        getInput();
        ballGamePlaying();
    }
    static void testCase123() {
        _arr_n[0] = 1;
        _arr_n[1] = 2;
        _arr_n[2] = 3;
        for (int i = 0; i < 5; i++) {
            _arr_x[i] = i + 1;
        }
    }
    static void testCase145() {
        _arr_n[0] = 1;
        _arr_n[1] = 4;
        _arr_n[2] = 5;
        for (int i = 0; i < 5; i++) {
            _arr_x[i] = i + 10;
        }
        _arr_x[4] = 15;
    }
    static void testCase235() {
        _arr_n[0] = 2;
        _arr_n[1] = 3;
        _arr_n[2] = 5;
        for (int i = 0; i < 5; i++) {
            _arr_x[i] = i + 7;
        }
    }
}

 

 

结果:

+ 0 + 0 -
+ 0 + 0 -:标准答案
0 - 0 + +
0 - 0 + +:标准答案
+ 0 0 0 0
+ 0 0 0 0:标准答案

 

posted on 2018-01-13 21:51  talkwah  阅读(1201)  评论(0编辑  收藏  举报