Loading

高僧斗法

古时丧葬活动中经常请高僧做法事。
仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛。

节目大略步骤为:先用粮食(一般是稻米)在地上“画”出若干级台阶(表示N级浮屠)。
又有若干小和尚随机地“站”在某个台阶上。
最高一级台阶必须站人,其它任意。(如图所示)

两位参加斗法的法师分别指挥某个小和尚向上走任意多级的台阶,但会被站在高级台阶上的小和尚阻挡,不能越过。
两个小和尚也不能站在同一台阶,也不能向低级台阶移动。

两法师轮流发出指令,最后所有小和尚必然会都挤在高段台阶,再也不能向上移动。
轮到哪个法师指挥时无法继续移动,则游戏结束,该法师认输。

对于已知的台阶数和小和尚的分布位置,请你计算先发指令的法师该如何决策才能保证胜出。

输入数据为一行用空格分开的N个整数,表示小和尚的位置。台阶序号从1算起,所以最后一个小和尚的位置即是台阶的总数。(N<100, 台阶总数<1000)

输出为一行用空格分开的两个整数: A B, 表示把A位置的小和尚移动到B位置。
若有多个解,输出A值较小的解,若无解则输出-1。

例如:
用户输入:
1 5 9
则程序输出:
1 4

再如:
用户输入:
1 5 8 10
则程序输出:
1 3

// 组合博弈论....转化为尼姆堆

public class Main {
    static boolean f(int[] x) {
        int sum = 0;
        for (int i = 0; i < x.length - 1; i += 2) {
            sum ^= x[i + 1] - x[i] - 1; // 两人一组间的空台阶数===>尼姆堆
        }
        return sum != 0;
    }

    static void solve(int[] x) {
        for (int i = 0; i < x.length - 1; i++) {
            for (int k = x[i] + 1; k < x[i + 1]; k++) {
                int old = x[i]; // 试着走
                try {
                    x[i] = k;
                    if (f(x) == false) {
                        System.out.println(old + " " + k);
                        return;
                    }
                } finally {
                    x[i] = old; // 回溯
                }
            }
        }
    }

    public static void main(String[] args) {
        solve(new int[] { 1, 5, 9 });
        solve(new int[] { 1, 5, 8, 10 });
        solve(new int[] { 1, 4, 8, 12, 16, 19, 28, 33, 35, 36, 40, 45, 52, 66, 67, 68, 69, 77, 85, 99, 102, 134, 155,
                211, 214, 216, 355, 376, 400, 412 });
    }
}

 

posted @ 2018-03-26 19:39  机智的小白  阅读(366)  评论(0编辑  收藏  举报