LCP 41. 黑白翻转棋
难度中等32
在 n*m
大小的棋盘中,有黑白两种棋子,黑棋记作字母 "X"
, 白棋记作字母 "O"
,空余位置记作 "."
。当落下的棋子与其他相同颜色的棋子在行、列或对角线完全包围(中间不存在空白位置)另一种颜色的棋子,则可以翻转这些棋子的颜色。
「力扣挑战赛」黑白翻转棋项目中,将提供给选手一个未形成可翻转棋子的棋盘残局,其状态记作 chessboard
。若下一步可放置一枚黑棋,请问选手最多能翻转多少枚白棋。
注意:
- 若翻转白棋成黑棋后,棋盘上仍存在可以翻转的白棋,将可以 继续 翻转白棋
- 输入数据保证初始棋盘状态无可以翻转的棋子且存在空余位置
示例 1:
输入:
chessboard = ["....X.","....X.","XOOO..","......","......"]
输出:
3
解释:
可以选择下在[2,4]
处,能够翻转白方三枚棋子。
示例 2:
输入:
chessboard = [".X.",".O.","XO."]
输出:
2
解释:
可以选择下在[2,2]
处,能够翻转白方两枚棋子。
示例 3:
输入:
chessboard = [".......",".......",".......","X......",".O.....","..O....","....OOX"]
输出:
4
解释:
可以选择下在[6,3]
处,能够翻转白方四枚棋子。
提示:
1 <= chessboard.length, chessboard[i].length <= 8
chessboard[i]
仅包含"."、"O"
和"X"
BFS
https://leetcode.cn/problems/fHi6rV/solution/python3javacgo-yi-ti-yi-jie-bfs-by-lcbin-e4vo/
class Solution {
int[][] dirts = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {-1, -1}, {-1, 1}, {1, -1}};
int m, n;
String[] chessboard;
public int flipChess(String[] chessboard) {
this.chessboard = chessboard;
m = chessboard.length; n = chessboard[0].length();
int ans = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(chessboard[i].charAt(j) == '.'){
ans = Math.max(ans, bfs(i, j));
}
}
}
return ans;
}
// 尝试枚举所有的空余位置作为下一步放置黑棋的位置,然后使用广度优先搜索的方法计算在该位置下可以翻转的白棋的数量
public int bfs(int i, int j){
Deque<int[]> q = new ArrayDeque<>();
q.offer(new int[]{i, j});
char[][] g = new char[m][0];
for(int k = 0; k < m; k++){
g[k] = chessboard[k].toCharArray();
}
int cnt = 0;
// 不断取出队首位置,遍历棋盘的八个方向,
// 如果该方向上是一段连续的白棋,且在末尾是黑棋,则将该黑棋之前的所有白棋都可以翻转,
// 将这些白棋的位置放入队列中,继续进行广度优先搜索。
while(!q.isEmpty()){
int[] p = q.poll();
i = p[0]; j = p[1];
for(int[] d : dirts){
int x = i + d[0], y = j + d[1];
while(x >= 0 && x < m && y >= 0 && y < n && g[x][y] == 'O'){
x += d[0];
y += d[1];
}
if(x >= 0 && x < m && y >= 0 && y < n && g[x][y] == 'X'){
x -= d[0];
y -= d[1];
cnt += Math.max(Math.abs(x - i), Math.abs(y - j));
// 将这些白棋的位置放入队列中,继续进行广度优先搜索。
while(x != i || y != j){
g[x][y] = 'X';
q.offer(new int[]{x, y});
x -= d[0];
y -= d[1];
}
}
}
}
return cnt;
}
}