2016年藍橋杯java B組第9題取球博弈
阿新 • • 發佈:2019-01-08
import java.util.Scanner; class Problem { private int N; private char[][][] dp; private int[] n = new int[3]; private int min = Integer.MAX_VALUE; Problem(int N, int[] n) { this.N = N; this.n = n; init(); } private void init() { dp = new char[2][N + 1][N + 1]; for (int i = 0; i < 3; i++) { min = Math.min(min, n[i]); } } // p是player的意思 // dp[p][A][B]表示先手方取了A個球,後手方取了B個球 // 現在輪到玩家p,最後先手方的輸贏情況 char dfs(int p, int A, int B) { if (dp[p][A][B] != '\u0000') return dp[p][A][B]; // 沒有球可取了,判輸贏 if (N - A - B < min) { if ((A & 1) == 1 && (B & 1) == 0) // A奇B偶,A勝 dp[p][A][B] = '+'; else if ((A & 1) == 0 && (B & 1) == 1) // B奇A偶,B勝 dp[p][A][B] = '-'; else dp[p][A][B] = '0'; // A沒勝B也沒勝,說明平 return dp[p][A][B]; } if (p == 0) { // 0號玩家,即先手一方 boolean flag = false; for (int i = 0; i < 3; i++) { if (A + n[i] + B <= N) { // 1號玩家說他輸,即0號玩家贏 if (dfs(1, A + n[i], B) == '+') return dp[0][A][B] = '+'; // 1號玩家說平,但0號玩家可能還有能贏的選擇 else if (dfs(1, A + n[i], B) == '0') flag = true; } if (flag) dp[0][A][B] = '0'; // 平 else dp[0][A][B] = '-'; // 0號玩家輸 } } else if (p == 1) { // 1號玩家,即後手一方 boolean flag = false; for (int i = 0; i < 3; i++) { if (A + n[i] + B <= N) { // 0號玩家說他輸 if (dfs(0, A, B + n[i]) == '-') return dp[1][A][B] = '-'; // 0號玩家說平,但1號玩家可能還有能贏的選擇 else if (dfs(0, A, B + n[i]) == '0') flag = true; } } if (flag) dp[1][A][B] = '0'; // 平 else dp[1][A][B] = '+'; // 1號玩家贏 } return dp[p][A][B]; } } public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] n = new int[3]; for (int i = 0; i < 3; i++) { n[i] = sc.nextInt(); } boolean flag = true; for (int x = 0; x < 5; x++) { int N = sc.nextInt(); Problem pb = new Problem(N, n); if (flag) { System.out.print(pb.dfs(0, 0, 0)); flag = false; } else { System.out.print(" " + pb.dfs(0, 0, 0)); } } sc.close(); } }