2023-06-21每日一题
一、题目编号
LCP 41. 黑白翻转棋
二、题目链接
三、题目描述
在 n * m 大小的棋盘中,有黑白两种棋子,黑棋记作字母 “X”, 白棋记作字母 “O”,空余位置记作 “.”。当落下的棋子与其他相同颜色的棋子在行、列或对角线完全包围(中间不存在空白位置)另一种颜色的棋子,则可以翻转这些棋子的颜色。
「力扣挑战赛」黑白翻转棋项目中,将提供给选手一个未形成可翻转棋子的棋盘残局,其状态记作 chessboard。若下一步可放置一枚黑棋,请问选手最多能翻转多少枚白棋。
注意:
若翻转白棋成黑棋后,棋盘上仍存在可以翻转的白棋,将可以 继续 翻转白棋
输入数据保证初始棋盘状态无可以翻转的棋子且存在空余位置
提示:
- 1 <= chessboard.length, chessboard[i].length <= 8
- chessboard[i] 仅包含 “.”、“O” 和 “X”
四、解题代码
class Solution {
public:
const int dirs[8][2] = {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}
};
bool judge(const vector<string>& chessboard, int x, int y, int dx, int dy) {
x += dx;
y += dy;
while (0 <= x && x < chessboard.size() && 0 <= y && y < chessboard[0].size()) {
if (chessboard[x][y] == 'X') {
return true;
} else if (chessboard[x][y] == '.') {
return false;
}
x += dx;
y += dy;
}
return false;
}
int bfs(vector<string> chessboard, int px, int py) {
int cnt = 0;
queue<pair<int, int>> q;
q.emplace(px, py);
chessboard[px][py] = 'X';
while (!q.empty()) {
pair<int, int> t = q.front();
q.pop();
for (int i = 0; i < 8; ++i) {
if (judge(chessboard, t.first, t.second, dirs[i][0], dirs[i][1])) {
int x = t.first + dirs[i][0], y = t.second + dirs[i][1];
while (chessboard[x][y] != 'X') {
q.emplace(x, y);
chessboard[x][y] = 'X';
x += dirs[i][0];
y += dirs[i][1];
++cnt;
}
}
}
}
return cnt;
}
int flipChess(vector<string>& chessboard) {
int res = 0;
for (int i = 0; i < chessboard.size(); ++i) {
for (int j = 0; j < chessboard[0].size(); ++j) {
if (chessboard[i][j] == '.') {
res = max(res, bfs(chessboard, i, j));
}
}
}
return res;
}
};
五、解题思路
(1) 采用广度优先搜索+状态压缩即可,
(2) 要学会使用二进制来表示状态。