Blue Bridge cup solution to a problem - monks battle of wits

topic

Monks battle of wits

Ancient funerals often ask monk approach things. After the ceremony, sometimes "monks battle of wits" fun program to relieve the oppressive atmosphere.

Program roughly steps: first with food (usually rice) on the ground "painting" a number of steps (N represents the level Buddha). There are several young monk at random "stand" on a certain level. Steps must stand on the highest level, any other. (As shown in Figure 1)

Two Master participate in the game novices are commanding a multi-level go up any stairs, but the young monk will be standing on the advanced level blocking, can not cross. Two novices can not stand on the same level, can not move to a lower level.

Master instructs two turns, and finally all novices are inevitably crowded high-stage step, can no longer be moved upward. Which can not continue to move when the command of the Master's turn, the game is over, the Master throw in the towel.

For the known position of the step number and distribution of novices, you calculate the starting instruction of Master how decision-making in order to ensure win.

Input data line separated by a space of N integers, it indicates the position of novices. No. 1 from the step counting, the final position that is a total number of novices step. (N <100,
the total number of steps <1000)

Output line separated by a space of two integers: AB, A represents the location of the mobile novices to the B position. If a plurality of solutions, a small value of solution A output, then outputs -1 if no solutions.

E.g:

User input:

1 5 9

The program output:

1 4

Another example:

User input:

1 5 8 10

The program output:

1 3

Resources for:

Peak memory consumption <64M

CPU consumption <1000ms

Please strictly follow the requirements of output, not superfluous to print something like: "Please enter ..." unwanted content.

All source code in a single file, through debugging, submit the copy source.

Game ordinary Solution

Write pictures described here

For a particular situation, assuming that the young monk station location 1 5 8 10for each monk, try every few steps he is currently able to walk recursively determine whether the new situation , if it is to return immediately if the current situation in each each monk tried to take the law are still not get the result, that the current Master, the problem has no solution.

package org.lanqiao.algo.lanqiaobei.game;

import java.util.Scanner;

public class 高僧斗法 {

  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    String[] ss = scanner.nextLine().split(" ");
    int[] x = new int[ss.length];
    //将小和尚的位置作为数组元素的值
    for (int i = 0; i < x.length; i++)
      x[i] = Integer.parseInt(ss[i]);
    if (!f(x)) {
      System.out.println(-1);
    } else {
      System.out.println(a + " " + b);
    }
  }

  static int a;
  static int b;

  private static boolean f(int[] x) {
    for (int i = 0; i < x.length - 1; i++) {
      //i位置向后尝试每一个可走的位置
      for (int j = x[i] + 1; j < x[i + 1]; j++) {
        int old = x[i];//记录i位置的原始值
        x[i] = j; //该表i位置的值
        try {
          //生成新的局面,如果这个局面判定对方输,那我们就赢了
          if (!f(x)) {
            a = old;
            b = j;
            return true;
          }
        } finally {
          x[i] = old;// 恢复i位置的值,进行下一次尝试
        }
      }
    }
    //for循环无法进行,或者整个for循环走完都没有一次变动能造成对方输,就返回false
    return false;
  }
}

The method that can cope with 1 5 8 10such an input, i.e. the number of small, the spacing is small, if the input is 1 30 40 99within a predetermined time calculation can not be completed.

Nimes heap Solution

About Nim, the venue and how to win in the game to take coins? (Game Theory Nimes) - know almost first understand the definition.

Monks battle of wits problem, how to take similar converted into coins such Nimes-set it?
We can generate a combination of two novices as a bunch (pile number intervals), for the input 1 5 8 10, the stack is converted to Nim N = {3,1}. If an odd number novices, such as 1 5 8 10 13, our monk in a virtual highest order, the number of such third stack is 0, then the stack Nim N = {3,1,0}.

For such Nimes heap, we just get a heap together all the elements XOR result is 0, then we are in the situation of losing the upper hand, if all exclusive or it is not 0, then we can change a bunch of Nimes heap size to facilitate XOR value is 0, so the losing situation leave each other.

Doing so can greatly enhance the efficiency, since only need to calculate the initial form, without considering how to go back, because once formed P-position, the other no matter how I can go back to the P-position.

Here's a more difficult question is figured, why it combined two by two, the interval between the combination does not consider it?
Write pictures described here

If we take the No. 5 novices, no matter how walking can follow each other, so we established Nimes heap without any change, that is, you create a P-positionrival and a back you P-position. If we changed the monks by number 2,8 Nimes heap, or to form a disparate 0 of P-positionsituation, then we can go no matter what the opponents to follow or change another Nimes to give each other a heap P-position.

Well, the bar code; compare burning brain:

static boolean f1(int[] x) {
    int[] N = new int[x.length / 2];// 堆的大小
    for (int i = 0; i < N.length; i++) {
      N[i] = x[2 * i + 1] - x[2 * i]-1;// 计算每个堆的数字
    }
    int k = N[0];
    for (int i = 1; i < N.length; i++) {
      k ^= N[i]; //连续做异或
    }
    // 现在异或不为0
    if (k != 0) {
      // 找到ni,其x位(k最高位)为1
      String kBinary = Integer.toBinaryString(k);
      for (int i = 0; i < N.length; i++) {
        //当前堆数字的二进制字符串
        String NiBinary = Integer.toBinaryString(N[i]);
        try {
          //右对齐后和k最高位在同一列的二进制为1
          if (NiBinary.charAt(NiBinary.length() - kBinary.length()) == '1') {
            a = x[2*i];  // 首动位置找到了
            //现在Ni 变为Ni' 使得尼姆堆的全体数字异或为0 只需把k所有为1的位对应的Ni上的位做0~1变换
            int Nii = N[i];
            for (int j = 0; j < kBinary.length(); j++) {
              if (kBinary.charAt(j)=='1')
                Nii^=(1<<(kBinary.length()-j-1));
            }

            // N[i]变为Nii肯定是缩小了,缩小的数就是a应该前进的数
            b = a+N[i]-Nii;
            break;
          }
        } catch (Exception e) {
          // 位数不够
        }
      }
      return true;
    }
    return false;
  }

Even after the improvements input 1 30 40 99, you can quickly calculate the answer.

Published 127 original articles · 98 won praise · views 310 000 +

Guess you like

Origin blog.csdn.net/zhengwei223/article/details/78615803