1450C2 Errich-Tac-Toe (Hard Version)(思维)
Codeforces Global Round 12
C2. Errich-Tac-Toe (Hard Version)
题面:Errich-Tac-Toe (Hard Version)
题意:有一个 n ∗ n n * n n∗n 的棋盘,上面每个格子内要么是空的,要么包含棋子 X X X 或者棋子 O O O,如果存在连续三个 X X X 或者连续三个 O O O 在同一排或者同一列则该局面不是平局,否则就是平局。现在可以进行翻转操作,一次可以将一个 X X X 变成 O O O 或者将一个 O O O 变成 X X X,现在问如何通过不超过 ⌊ k 3 ⌋ \lfloor\frac{k}{3}\rfloor ⌊3k⌋ 次操作让局面变成平局,其中 k k k 是棋盘中非空格子的数量。
范围: 1 ≤ n ≤ 300 1 \le n \le 300 1≤n≤300。
分析: 我们可以思考出这样一个结论:如果我们能让连续的三个棋子中至少出现一个 X X X 和一个 O O O,那么就能避免三个连续相同棋子的情况,形成平局。

(相当于我们需要选择间隔相同的
X
X
X 对角线与
O
O
O 对角线对棋盘进行分割,避免出现三个棋子同色的情况)
同一排或者同一列三个连续的棋子满足 ( i + j ) % 3 = = 0 , 1 , 2 (i + j) \% 3 == 0, 1, 2 (i+j)%3==0,1,2,因此我们可以按照 ( i + j ) % 3 (i+j)\%3 (i+j)%3 来对所有的 X X X 与 O O O 进行统计,假设数量为 x 0 , x 1 , x 2 , o 0 , o 1 , o 2 x0,x1,x2,o0,o1,o2 x0,x1,x2,o0,o1,o2,显然 k = x 0 + x 1 + x 2 + o 0 + o 1 + o 2 k = x0+x1+x2+o0+o1+o2 k=x0+x1+x2+o0+o1+o2,需要使得连续的三个棋子中至少出现一个 X X X 和一个 O O O,那么我们需要在 x 0 , x 1 , x 2 x0,x1,x2 x0,x1,x2 中选择一个并且在 o 0 , o 1 , o 2 o0,o1,o2 o0,o1,o2 中选择一个位置不同的进行修改操作,找到最小的 x i + o j xi+oj xi+oj,它一定满足 x i + o j ≤ ⌊ k 3 ⌋ xi+oj\le \lfloor\frac{k}{3}\rfloor xi+oj≤⌊3k⌋,最后根据选择的两个数字对棋盘棋子进行翻转输出即可。
Code:
#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
const int MAXN = 300 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);
int n, m, k;
char arr[MAXN][MAXN];
int num_x[3], num_y[3];
signed main()
{
int T = read();
while (T--)
{
memset(num_x, 0, sizeof(num_x));
memset(num_y, 0, sizeof(num_y));
n = read();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> arr[i][j];
if (arr[i][j] == 'X') num_x[(i + j) % 3]++;
else if (arr[i][j] == 'O') num_y[(i + j) % 3]++;
}
}
int idx1 = 0, idx2 = 0;
int minV = INF;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i == j) continue;
if (minV > num_x[i] + num_y[j])
{
minV = num_x[i] + num_y[j];
idx1 = i, idx2 = j;
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (arr[i][j] == 'X' && (i + j) % 3 == idx1)
{
arr[i][j] = 'O';
}
else if (arr[i][j] == 'O' && (i + j) % 3 == idx2)
{
arr[i][j] = 'X';
}
cout << arr[i][j];
}
cout << endl;
}
}
return 0;
}
【END】感谢观看
261

被折叠的 条评论
为什么被折叠?



