Blue Bridge cup solution to a problem - take the ball Game 1

topic

This box has n balls, A, B two take turns to take the ball from the box, everyone can see how many other people take,
we can also see how much is left in a box, and the two very smart, does not make wrong judgments.
Our convention:
the number of each ball removed from the box must be: 1, 3, 7 or 8.
A party can not turn to abstain when taking the ball!
A first take the ball, take the ball and then alternating sides until take complete.
The party was forced to get the last ball of the loser (losers)
Make programming is not determined in the case of both the misjudgment, for a specific number of initial ball, A whether win?
When the program runs, the data obtained from the standard input, the format is as follows:
First, an integer n (n <100), next with n represents an integer. N is an integer then, line each (integer <10000) indicating that the initial number of balls.
Program output n lines, where A represents a winning or losing (the input is 0, 1 win).
For example, a user input:
. 4
. 1
2
10
18 is
the application should Output:
0
. 1
. 1
0

Recursive solution

Recursive solution is easier to think of:

f(int n)
  if(n==0) 对方把球取完了,我赢了,return true;
  if(n>=1 && 我取1个,对方一定为负) return true;
  if(n>=3 && 我取3个,对方一定为负) return true;
  if(n>=7 && 我取7个,对方一定为负) return true;
  if(n>=8 && 我取8个,对方一定为负) return true;
  return false;

Code:

  public static boolean pick1(int n){
    if (n==0)
      return true;
    if (n>=1&&!pick1(n-1))
      return true;
    if (n>=3&&!pick1(n-3))
      return true;
    if (n>=7&&!pick1(n-7))
      return true;
    if (n>=8&&!pick1(n-8))
      return true;
    return false;
  }

The main method of processing input and output:

  public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    int[] x = new int[n];
    for (int i = 0; i < x.length; i++) {
      x[i] = scan.nextInt();
    }
    scan.close();
    for (int i = 0; i < x.length; i++) {
      System.out.println(pick1(x[i]) ? 1 : 0);
    }
  }

However, this solution has a problem, when n is large, too inefficient, because a lot of double counting items.

Memory type recursive

General problem of such double counting, you can use the recursive memory.

  static Map<Integer, Boolean> cache = new HashMap<>();

  /**
   * @param n  代表当前所剩球的个数
   * @return true:我方赢
   */

  static boolean pick2(int n) {
    //对方拿完了,我就赢了
    if (n == 0)
      return true;
    if (cache.get(n) != null)
      return cache.get(n);
    //大于1,我取1,剩下局面(n-1)对方输,则我方赢
    if (n >= 1 && !pick2(n - 1)) {
      cache.put(n, true);
      return true;
    }
    if (n >= 3 && !pick2(n - 3)) {
      cache.put(n, true);
      return true;
    }
    if (n >= 7 && !pick2(n - 7)) {
      cache.put(n, true);
      return true;
    }
    if (n >= 8 && !pick2(n - 8)) {
      cache.put(n, true);
      return true;
    }
    cache.put(n, false);
    return false;
  }

Dynamic Programming

Alternatively, you can write a recursive, recursive digital small to N:

f(N) = true | f(N-1)=false或者f(N-3)=false或者f(N-7)=false或者f(N-8)=false
f(N) = false | N=1

On the code:

  public static boolean pick(int n) {
    if (n <= 0)
      return false;
    boolean[] state = new boolean[n + 1];
    state[1] = false;

    for (int i = 2; i <= n; i++) {
      boolean flag3;
      if (i - 3 <= 0)
        flag3 = false;
      else
        flag3 = !state[i - 3];

      boolean flag7;
      if (i - 7 <= 0)
        flag7 = false;
      else
        flag7 = !state[i - 7];

      boolean flag8;
      if (i - 8 <= 0)
        flag8 = false;
      else
        flag8 = !state[i - 8];
      //这就是递推式对应的代码
      state[i] = !state[i - 1] || flag3 || flag7 || flag8;
    }
    return state[n];
  }

For general recursive process from recursive to see dynamic programming (a) DynamicProgramming - CSDN blog

There are also Blue Bridge Bowl coaching video oh

Published 127 original articles · won 97 Like · views 310 000 +

Guess you like

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