Errich-Tac-Toe
Problem Description
Errichto gave Monogon the following challenge in order to intimidate him from taking his top contributor spot on Codeforces.
In a Tic-Tac-Toe grid, there are
n
n
n rows and
n
n
n columns. Each cell of the grid is either empty or contains a token. There are two types of tokens: X and O. If there exist three tokens of the same type consecutive in a row or column, it is a winning configuration. Otherwise, it is a draw configuration.
In an operation, you can change an X to an O, or an O to an X. Let
k
k
k denote the total number of tokens in the grid. Your task is to make the grid a draw in at most
⌊
k
3
⌋
\left\lfloor\frac{k}{3}\right\rfloor
⌊3k⌋(rounding down) operations.
You are not required to minimize the number of operations.
Input
The first line contains a single integer t t t ( 1 ≤ t ≤ 100 1≤t≤100 1≤t≤100) — the number of test cases.
The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 300 1≤n≤300 1≤n≤300) — the size of the grid.
The following n n n lines each contain a string of n n n characters, denoting the initial grid. The character in the i i i-th row and j j j-th column is ‘.’ if the cell is empty, or it is the type of token in the cell: ‘X’ or ‘O’.
It is guaranteed that not all cells are empty.
The sum of n n n across all test cases does not exceed 300.
Output
For each test case, print the state of the grid after applying the operations.
We have proof that a solution always exists. If there are multiple solutions, print any.
Sample Input
3
3
.O.
OOO
.O.
6
XXXOOO
XXXOOO
XX…OO
OO…XX
OOOXXX
OOOXXX
5
.OOO.
OXXXO
OXXXO
OXXXO
.OOO.
Sample Output
.O.
OXO
.O.
OXXOOX
XOXOXO
XX…OO
OO…XX
OXOXOX
XOOXXO
.OXO.
OOXXO
XXOXX
OXXOO
.OXO.
题意
在 n ∗ n n*n n∗n的网格图中,部分网格被填充上了’X’令牌或’O’令牌。在一行或一列中,如果被填充上了连续三个相同类型的令牌,则称当前局面为胜局,否则称为平局。现在给出一种游戏的局面,网格中共有 k k k个令牌,最多进行 ⌊ k 3 ⌋ \left\lfloor\frac{k}{3}\right\rfloor ⌊3k⌋次操作,将其变为平局。给出一种合理解。
思路
设下标为
(
i
,
j
)
(i,j)
(i,j),对网格进行染色,根据
(
i
+
j
)
%
3
(i+j)\%3
(i+j)%3讲网格染成0,1,2三种不同的颜色。染色后,若某行或某列有三个连续的元素,则三个元素必然属于不同的颜色。所以考虑让某种颜色不包含‘O’,某种颜色不包含’X’即可。
C1:根据网格颜色,将元素放入vector中,求出元素最少的vector,将其中所有元素变为‘O’即可。
设三种颜色的数量分别为num0,num1,num2,且num0最小,则
3
∗
n
u
m
0
≤
n
u
m
0
+
n
u
m
1
+
n
u
m
2
=
k
3*num0\le num0+num1+num2=k
3∗num0≤num0+num1+num2=k
C2: 根据网格颜色,令牌符号将元素放入vector中,将某种颜色的网格中所有的’X’变成‘O’,某种颜色的网格中所有的’O’变成‘X’,这样则满足一种颜色的网格中没有’X’,一种颜色的网格中没有’O’。求出最小的
i
d
1
,
i
d
2
(
i
d
1
!
=
i
d
2
)
id_1,id_2(id_1!=id_2)
id1,id2(id1!=id2),满足
g
[
i
d
1
]
[
0
]
.
s
i
z
e
(
)
+
g
[
i
d
2
]
[
1
]
.
s
i
z
e
(
)
g[id_1][0].size()+g[id_2][1].size()
g[id1][0].size()+g[id2][1].size()最小。
设vector大小分别为num00,num01,num10,num11,num20,num21,假设
i
d
1
=
0
,
i
d
2
=
1
id_1 = 0, id_2 = 1
id1=0,id2=1,则
3
∗
(
n
u
m
00
+
n
u
m
11
)
≤
(
n
u
m
00
+
n
u
m
11
)
+
(
n
u
m
10
+
n
u
m
21
)
+
(
n
u
m
20
+
n
u
m
01
)
=
k
3*(num00+num11)\le (num00+num11)+(num10+num21)+(num20+num01) = k
3∗(num00+num11)≤(num00+num11)+(num10+num21)+(num20+num01)=k。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 320;
const int mod = 998244353;
char str[maxn][maxn];
vector<P> g[4][4];
int main()
{
int t, n, m, i, j, k;
scanf("%d", &t);
while(t--)
{
for(i=0;i<4;i++){
g[i][0].clear();
g[i][1].clear();
}
scanf("%d", &n);
for(i=0;i<n;i++)
scanf("%s", str[i]);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(str[i][j] == 'O')g[(i+j)%3][0].push_back(P(i,j));
else if(str[i][j] == 'X') g[(i+j)%3][1].push_back(P(i, j));
int id1, id2, mx = INF;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(i!=j && g[i][0].size()+g[j][1].size()<mx){
mx = g[i][0].size()+g[j][1].size();
id1 = i, id2 = j;
}
for(i=0;i<g[id1][0].size();i++){
P p = g[id1][0][i];
str[p.first][p.second] = 'X';
}
for(i=0;i<g[id2][1].size();i++){
P p = g[id2][1][i];
str[p.first][p.second] = 'O';
}
for(i=0;i<n;i++)
printf("%s\n", str[i]);
}
return 0;
}