问题 F: Hexagon Game
时间限制: 1 Sec 内存限制: 128 MB
提交: 5 解决: 2
[ 提交][ 状态][ 讨论版]题目描述
This problem was inspired by a board game called Hex, designed independently by Piet Hein and John Nash. It has a similar idea, but does not assume you have played Hex. This game is played on an NxN board, where each cell is a hexagon. There are two players: Red side (using red stones) and Blue side (using blue stones). The board starts empty, and the two players take turns placing a stone of their color on a single cell within the overall playing board. Each player can place their stone on any cell not occupied by another stone of any color. There is no requirement that a stone must be placed beside another stone of the same color. The player to start first is determined randomly (with equal probability among the two players). The upper side and lower sides of the board are marked as red, and the other two sides are marked as blue. The goal of the game is to form a connected path of one player's stones connecting the two sides of the board that have that player's color. The first player to achieve this wins. Note that the four corners are considered connected to both colors. The game ends immediately when one player wins. Given a game state, help someone new to the game determine the status of a game board. Say one of the following: "Impossible": If it was impossible for two players to follow the rules and to have arrived at that game state. "Red wins": If the player playing the red stones has won. "Blue wins": If the player playing the blue stones has won. "Nobody wins": If nobody has yet won the game. Note that a game of Hex can't end without a winner! Note that in any impossible state, the only correct answer is "Impossible", even if red or blue has formed a connected path of stones linking the opposing sides of the board marked by his or her colors. Here's a an example game on a 6x6 gameboard where blue won. Blue was the first player to move, and placed a blue stone at cell marked as 1. Then Red placed at cell 2, then blue at cell 3, etc. After the 11th stone is placed, blue wins.
输入要求
The first line of input gives the number of test cases, T(1 ≤ T ≤ 100). T test cases follow.
Each test case start with the size of the side of the board, N(1 ≤ N ≤ 100).
This is followed by a board of N rows and N columns consisting of only 'B', 'R' and '.' characters.
'B' indicates a cell occupied by blue stone, 'R' indicates a cell occupied by red stone, and '.' indicates an empty cell.
输出要求
For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the status of the game board.
It can be "Impossible", "Blue wins", "Red wins" or "Nobody wins" (excluding the quotes).
假如输入
7 1 . 1 B 1 R 2 BR BB 4 BBBB BBB. RRR. RRRR 4 BBBB BBBB RRR. RRRR 6 ...... ..R... BBBBBB ..R.R. ..RR.. ......
应当输出
Case #1: Nobody wins Case #2: Blue wins Case #3: Red wins Case #4: Impossible Case #5: Blue wins Case #6: Impossible Case #7: Blue wins
提示
1、首先进行六边形棋盘与矩形的转换: 关于方向上的问题解决方案如下: 如上图所示,以6为中心,在矩形内本该有上、下、左、右、左上、左下、右上、右下8个遍历方向,由于六边形六条边面的特性(只与周围其他六个六边形相连),即没有左上和右下的方向。 2、获胜的条件: (1)所给的棋盘状态下的棋子摆放合理: (i)按照每人每次轮流下一步的规则,两种颜色的棋子总数最多相差一个,或者相等。 (ii)按照规则,一旦有一方获胜游戏即刻停止。即不可能出现某一方获胜两次及以上,或者,两方都获胜的情况。 (2)对于红方:红色棋子将棋盘的上下边相连。 对于蓝方:蓝色棋子将棋盘的左右边相连。 注:本来应该先判断棋盘上的棋子布局是否合理,但是检查合理性会很费时,应当先检查输赢或者与检查输赢一起进行。
源码:import java.util.Scanner; public class Main { //定义四种游戏最终状态,并与RESULT里的字符串一一对应 public static final int BLUE_WINS = 0; public static final int IMPOSSIBLE = 1; public static final int RED_WINS = 2; public static final int NOBODY_WINS = 3; public static final String[] RESULT = { "Blue wins", "Impossible", "Red wins", "Nobody wins" }; //蓝方和红方赢得比赛的次数 public static int blueWinCount = 0; public static int redWinCount = 0; /** * 判断双方的棋子数量是否合理(双方棋子数量的差的绝对值不超过1),因为是轮流每人下一颗棋 * @param map * @return */ private static boolean isCellNumberReasonable(char[][] map) { int bCount = 0, rCount = 0; for (int i = 0; i < map.length; i++) { for (int j = 0; j < map.length; j++) { if (map[i][j] == 'B') { bCount++; } else if (map[i][j] == 'R') { rCount++; } } } // System.out.println("CountCha=" + Math.abs(bCount - rCount)); return Math.abs(bCount - rCount) <= 1; } /** * 判断蓝方是否赢得比赛 * @param map * @param x * @param y * @return */ public static boolean isBlueWin(char[][] map, int x, int y) { map[x][y] = '.';//将遍历过的位置改为“.”,防止出现循环遍历的情况 if (y == map.length - 1) { blueWinCount++; } // UP if (y - 1 >= 0 && map[x][y - 1] == 'B') { isBlueWin(map, x, y - 1); } // RIGHT_UP if (x + 1 < map.length && y - 1 >= 0 && map[x + 1][y - 1] == 'B') { isBlueWin(map, x + 1, y - 1); } // RIGHT if (x + 1 < map.length && map[x + 1][y] == 'B') { isBlueWin(map, x + 1, y); } // DOWN if (y + 1 < map.length && map[x][y + 1] == 'B') { isBlueWin(map, x, y + 1); } // LEFT_DOWN if (x - 1 >= 0 && y + 1 < map.length && map[x - 1][y + 1] == 'B') { isBlueWin(map, x - 1, y + 1); } // LEFT if (x - 1 >= 0 && map[x - 1][y] == 'B') { isBlueWin(map, x - 1, y); } return blueWinCount >= 1; } /** * 判断红方是否赢得比赛 * @param map * @param x * @param y * @return */ private static boolean isRedWin(char[][] map, int x, int y) { map[x][y] = '.';//将遍历过的位置改为“.”,防止出现循环遍历的情况 if (x == map.length - 1) { redWinCount++; } // UP if (y - 1 >= 0 && map[x][y - 1] == 'R') { isRedWin(map, x, y - 1); } // RIGHT_UP if (x + 1 < map.length && y - 1 >= 0 && map[x + 1][y - 1] == 'R') { isRedWin(map, x + 1, y - 1); } // RIGHT if (x + 1 < map.length && map[x + 1][y] == 'R') { isRedWin(map, x + 1, y); } // DOWN if (y + 1 < map.length && map[x][y + 1] == 'R') { isRedWin(map, x, y + 1); } // LEFT_DOWN if (x - 1 >= 0 && y + 1 < map.length && map[x - 1][y + 1] == 'R') { isRedWin(map, x - 1, y + 1); } // LEFT if (x - 1 >= 0 && map[x - 1][y] == 'R') { isRedWin(map, x - 1, y); } return redWinCount >= 1; } /** * 得到最终结果 * * @param map * @return */ public static int judge(char[][] map) { int n = map.length; int state = NOBODY_WINS; // 由于isBlueWin和isRedWin两个方法会修改map里的数据,所以要提前判断棋子数量书否合理 boolean isCellNumberReasonable = isCellNumberReasonable(map); for (int i = 0; i < n; i++) { if (map[i][0] == 'B' && isBlueWin(map, i, 0)) { state = BLUE_WINS; } if (map[0][i] == 'R' && isRedWin(map, 0, i)) { state = RED_WINS; } } // 如果蓝方和红方赢得比赛的次数超过1,或者,棋子数量不合理,则判定游戏当前状态为impossible if (blueWinCount + redWinCount > 1 || !isCellNumberReasonable) { state = IMPOSSIBLE; } // System.out.println("WinCount=" + (blueWinCount + redWinCount)); return state; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); int z = cin.nextInt(); for (int j = 1; j <= z; j++) { int n = cin.nextInt(); char[][] map = new char[n][n]; for (int i = 0; i < map.length; i++) { map[i] = cin.next().toCharArray(); } // 每次初始化蓝方和红方赢得比赛的次数 blueWinCount = 0; redWinCount = 0; System.out.println("Case #" + j + ": " + RESULT[judge(map)]); } } }
#算法有Bug,日后再改。
【数据结构+算法】浙传OJ Contest 2290:13信息1 Java 6 问题 F: Hexagon Game
最新推荐文章于 2018-10-19 08:06:53 发布