C2. Errich-Tac-Toe (Hard Version)
题意:给一个矩阵,里面有 k 个 'X' 或 'O' 标记,现在要修改不超过 k / 3 个标记('X'改成'O','O'改成'X'),使得矩阵中没有三个连续的相同的标记
思路:对两种不同的标记分别修改(i + j)% 3 == opx,(i + j) % 3 == opo 的位置,前提是修改的个数要少于总标记数的三分之一,所以枚举opx和opo,然后判断是否合法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int N = 310;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
char s[N][N];
int main() {
int t, n;
scanf("%d", &t);
while(t--) {
int xx = 0, oo = 0;
scanf("%d", &n);
int x[3] = {0, 0, 0}, o[3] = {0, 0, 0};
for(int i = 0; i < n; ++i) scanf("%s", &s[i]);
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(s[i][j] == 'X') xx++, x[(i + j) % 3]++;
else if(s[i][j] == 'O') oo++, o[(i + j) % 3]++;
}
}
int opx = -1, opo = -1;
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
if(i == j) continue;
if(x[i] + o[j] <= (xx + oo) / 3) {
opx = i, opo = j;
break;
}
}
if(opx != -1) break;
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(s[i][j] == 'X' && (i + j) % 3 == opx) cout << 'O';
else if(s[i][j] == 'O' && (i + j) % 3 == opo) cout << 'X';
else cout << s[i][j];
}
cout<<'\n';
}
}
}