网址:https://leetcode.com/problems/n-queens-ii/
方法1:按照逻辑思路,通过回溯法解决问题。速度较慢!
class Solution { public: void backTracking(vector<string> res, int &ans, int r, int n) { bool legal = true; // 定义一个flag,用于判断某一行中的某个位置是否合法 if(r == n) // 表示已经遍历完所有行 { ans++; return; } for(int j = 0; j<n; j++) // 判断当前行中的每个位置 { legal = true; for(int i = 0; i<=r-1; i++) // 判断此位置是否合法 { // 分别判断 列、副对角线、主对角线 // j - (r-i) if((res[i][j] == 'Q') || (res[i][j+i-r] == 'Q') || (res[i][j+r-i] == 'Q')) { // 说明此位置会被其他皇后攻击 legal = false; break; } } if(legal) { // 在此位置放置一个皇后 res[r][j] = 'Q'; // 将新的数据再次进行回溯 backTracking(res, ans, r+1, n); // 回溯完毕后切记恢复原来的状态,以剩余的for循环 res[r][j] = '.'; } } } int totalNQueens(int n) { string s(n, '.'); vector<string> vc(n, s); int ans = 0; backTracking(vc, ans, 0, n); return ans; } };
方法2:位运算
参考:https://www.bilibili.com/video/av46292575/?p=43
class Solution { public: void dfs(int &ans, int n, int row, int col, int pie, int na) { if(row == n) // 表示已经遍历完所有行 { ans++; return; } // 把int类型的col、pie、na以二进制来看待,0分别表示此格子不会被其他皇后以某种方式攻击,1表示会 // (col|pie|na)得到总的攻击情况,但我们需要的是当中 0 的位置,因为0的位置无法获取,所以 // 对(col|pie|na)取反,即'~'操作符。取反后,数据的后n位是满足我们的要求的 // 但是,前面原来的0都变成了1,所以要想办法把第n位之前的0还原为1 // (1 << n)-1) 即可产生000...001111这样一个数,将其&上原来的数,即可实现预想 int bits = ((~(col|pie|na))&((1 << n)-1)); while(bits) // { int pos = bits & -bits; // 得到一个只保留最后一位 1 ,其他的全为 0 的数 // 更新数据,注意对角线的挪移 dfs(ans, n, row+1, col|pos, (pie|pos)<<1, (na|pos)>>1); // 把bits去掉最后一位的 1 bits = bits & (bits-1); } } int totalNQueens(int n) { int ans = 0; dfs(ans, n, 0, 0, 0, 0); return ans; } };