题目链接
分析
因为最多只有四个棋子,所以枚举每种可能的情况,回溯进行统计即可
代码实现
struct Step {
int x, y, dx, dy, time; // 坐标、方向和步数
};
class Board {
private:
const int BOARDSIZE = 8;
int n = 0, ans = 0;
vector<vector<Step>> moves;
unordered_map<string, vector<pair<int, int>>> dir = {
{"rook", {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}},
{"bishop", {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}},
{"queen", {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {1, -1}, {-1, -1}, {-1, 1}}}
};
// 生成可到的格子
vector<Step> generatorMoves(string& pieces, vector<int>& position)
{
int x = position[0], y = position[1];
vector<Step> tmoves = {{x, y, 0, 0, 0}};
for(auto& [dx, dy] : dir[pieces])
{
int tx = x + dx, ty = y + dy;
for(int i = 1; tx > 0 && tx <= BOARDSIZE && ty > 0 && ty <= BOARDSIZE; ++i)
{
tmoves.emplace_back(x, y, dx, dy, i);
tx += dx, ty += dy;
}
}
return tmoves;
}
// 判断所给的两步是否有冲突
bool check(Step& a, Step& b)
{
int ax = a.x, ay = a.y, bx = b.x, by = b.y;
for(int i = 0; i < max(a.time, b.time); ++i)
{
if(i < a.time)
ax += a.dx, ay += a.dy;
if(i < b.time)
bx += b.dx, by += b.dy;
if(ax == bx && ay == by)
return false;
}
return true;
}
public:
Board(vector<string> &pieces, vector<vector<int>>& positions)
{
n = pieces.size();
for(int i = 0; i < n; ++i)
moves.emplace_back(generatorMoves(pieces[i], positions[i]));
}
// 回溯进行计算
int play()
{
vector<Step> record(n);
auto checkStep = [&](auto& checkStep, int idx) -> void {
if(idx == n)
{
ans++;
return ;
}
for(Step& s : moves[idx])
{
bool f = true;
for(int j = 0; j < idx; j++)
{
if(!check(s, record[j]))
{
f = false;
break;
}
}
if(f)
{
record[idx] = s;
checkStep(checkStep, idx + 1);
}
}
};
checkStep(checkStep, 0);
return ans;
}
};
class Solution {
public:
int countCombinations(vector<string>& pieces, vector<vector<int>>& positions) {
Board thisGame(pieces, positions);
thisGame.cm();
return thisGame.play();
}
};
复杂度分析
- 时间复杂度:$O(nST^n)$, 其中 $n$ 为棋子的个数,$S$ 为棋盘的大小,$T$ 为单个棋子的合法位置个数
- 空间复杂度:$O(nT)$