本文记录的是刷题过程中的重要概念和笔记。如有侵权,请联系删除。
原题
在 n*m 大小的棋盘中,有黑白两种棋子,黑棋记作字母 “X”, 白棋记作字母 “O”,空余位置记作 “.”。当落下的棋子与其他相同颜色的棋子在行、列或对角线完全包围(中间不存在空白位置)另一种颜色的棋子,则可以翻转这些棋子的颜色。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/fHi6rV
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
母题
八皇后问题,没有快捷方法,回溯爆搜
方法
广度优先搜索+回溯
对每一个空余位置尝试黑棋放置,用一个队列来存储正在进行「翻转操作」的黑棋位置,若有可以翻转的白棋,则将这些白旗进行翻转,并加入队列中。直至队列为空表示一次放置黑棋结束。
class Solution {
private:
const int dirs[8][2] = {
// 1*:将可能的八个方向以字典记录下来,从而实现代码归一化
{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}
};
bool judge(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 check(vector<string> chessboard, int x, int y){
// 注意参数:chessboard按值传递,因为不同位置需要更新为原来的棋盘。本质为回溯的改为原值。
// 回溯算法
// 终止条件:if(chessboard[x][y]!='.') return 0;
int res=0;
// 逐层的遍历通过队列存储,本质上是采用bfs
queue<pair<int,int>> que;
// 2*:que.push(pair<int,int>(x,y));注意写法
que.push(pair<int,int>(x,y));
while(!que.empty()){
// 处理当前队首节点
pair<int, int> tmp = que.front();
que.pop();
for(int i=0;i<8;i++){
if(judge(chessboard,tmp.first,tmp.second,dirs[i][0],dirs[i][1])){
int xTmp= tmp.first+dirs[i][0];
int yTmp= tmp.second+dirs[i][1];
while(chessboard[xTmp][yTmp]!='X'){
que.push(pair<int,int>(xTmp,yTmp));
chessboard[xTmp][yTmp]='X';
xTmp+=dirs[i][0];
yTmp+=dirs[i][1];
res++;
}
}
}
}
return res;
}
public:
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,check(chessboard,i,j));
}
}
return res;
}
};
复杂度
知识点
- 1*:将可能的八个方向以字典记录下来,从而实现代码归一化
- 2*:que.push(pair<int,int>(x,y));注意写法
补充
-
push_back和emplace_back的区别只在传入的参数是对象的构造参数时,如push_back(10),emplace_back(10)。
两种情况下:
push_back(10)会先调用类的有参构造函数,创建一个临时对象,再在容器的末尾调用类的右值构造函数(因为这个临时对象没有名字,属于右值,所以只能使用右值构造函数),输入临时对象的地址,创建一个新的对象,根据地址值到临时对象所在的内存空间中拷贝数据,最后再调用临时对象的析构函数,析构这个临时对象。emplace_back(10)少了临时对象这一步,直接在容器的末尾调用类的有参构造函数创建一个新的对象,完成添加操作。
版权声明:本文为CSDN博主「Zeehoy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44179561/article/details/124387475