CodeForces_1450C Errich-Tac-Toe(构造)

Errich-Tac-Toe

time limit per test:1 seconds
memory limit per test:256 megabytes
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 1t100) — 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 1n300) — 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 nn的网格图中,部分网格被填充上了’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 3num0num0+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值