题解:P11649 [COCI 2024/2025 #4] 棋 / Šah
题目链接
洛谷
朴素法
思路:
我们先按题目中说的,用二维数组记录下每个棋子可以攻击到的位置,最后做一个统计。时间复杂度:
AC 代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
int n, m, ans;
bool board[maxn][maxn];
int main() {
cin >> n >> m;
for(int i = 1; i <= m; ++i) {
char c;
int x, y;
cin >> c >> x >> y;
board[x][y] = true;
if(c == 'N') {
if(x - 2 >= 1 && y - 1 >= 1)
board[x - 2][y - 1] = true;
if(x - 2 >= 1 && y + 1 <= n)
board[x - 2][y + 1] = true;
if(x - 1 >= 1 && y - 2 >= 1)
board[x - 1][y - 2] = true;
if(x - 1 >= 1 && y + 2 <= n)
board[x - 1][y + 2] = true;
if(x + 2 >= 1 && y - 1 >= 1)
board[x + 2][y - 1] = true;
if(x + 2 >= 1 && y + 1 <= n)
board[x + 2][y + 1] = true;
if(x + 1 >= 1 && y - 2 >= 1)
board[x + 1][y - 2] = true;
if(x + 1 >= 1 && y + 2 <= n)
board[x + 1][y + 2] = true;
}
if(c == 'R') {
for(int x1 = x, y1 = y; x1 >= 1; --x1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 <= n; ++x1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; y1 >= 1; --y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; y1 <= n; ++y1)
board[x1][y1] = true;
}
if(c == 'Q') {
for(int x1 = x, y1 = y; x1 >= 1; --x1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 <= n; ++x1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; y1 >= 1; --y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; y1 <= n; ++y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 >= 1 && y1 >= 1; --x1, --y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 >= 1 && y1 <= n; --x1, ++y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 <= n && y1 >= 1; ++x1, --y1)
board[x1][y1] = true;
for(int x1 = x, y1 = y; x1 <= n && y1 <= n; ++x1, ++y1)
board[x1][y1] = true;
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
if(board[i][j] == true)
++ans;
cout << ans << endl;
return 0;
}
优化法
虽然 AC 了,我们再来想想能不能继续优化。
思路
再使用多个数组记录攻击信息,直接花
优化代码
注:在我的代码中
对于每条从左上往右下的对角线上的每个坐标为
#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
int n, m, ans;
bool board[maxn][maxn], f1[maxn], f2[maxn], f3[maxn * 2], f4[maxn * 2];
int main() {
cin >> n >> m;
for(int i = 1; i <= m; ++i) {
char c;
int x, y;
cin >> c >> x >> y;
board[x][y] = true;
if(c == 'N') {
if(x - 2 >= 1 && y - 1 >= 1)
board[x - 2][y - 1] = true;
if(x - 2 >= 1 && y + 1 <= n)
board[x - 2][y + 1] = true;
if(x - 1 >= 1 && y - 2 >= 1)
board[x - 1][y - 2] = true;
if(x - 1 >= 1 && y + 2 <= n)
board[x - 1][y + 2] = true;
if(x + 2 >= 1 && y - 1 >= 1)
board[x + 2][y - 1] = true;
if(x + 2 >= 1 && y + 1 <= n)
board[x + 2][y + 1] = true;
if(x + 1 >= 1 && y - 2 >= 1)
board[x + 1][y - 2] = true;
if(x + 1 >= 1 && y + 2 <= n)
board[x + 1][y + 2] = true;
}
if(c == 'R') {
f1[x] = true;
f2[y] = true;
}
if(c == 'Q') {
f1[x] = true;
f2[y] = true;
f3[x - y + n] = true;
f4[x + y - 1] = true;
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
if(board[i][j] == true || f1[i] == true || f2[j] == true || f3[i - j + n] == true || f4[i + j - 1] == true)
++ans;
cout << ans << endl;
return 0;
}
两份代码虽然都能过,但明显第二份代码更快。