思路
实际上,如果你会简单版本,那么困难版本也没有那么难了。
同样考虑构造一种通解,如下,

红色的格子改为 X,绿色的格子改为 O,就是一种通解,同样的,这样改可能会超过棋子总数的
1
3
\frac 1 3
31。
同样考虑将棋子按照位置分类,假如该棋子的位置是 ( i , j ) (i,j) (i,j),那么按照 ( i + j ) m o d 3 (i+j)\bmod 3 (i+j)mod3 的值分类即可,将值为 0 0 0 的看作第 0 0 0 类,值为 1 1 1 的看作第 1 1 1 类,将值为 2 2 2 的看作第 2 2 2 类。
显然的是,将所有第
0
0
0 类棋子改为 X,所有第
1
1
1 类棋子改为 O 是一种方案,还有将第 KaTeX parse error: Undefined control sequence: \2 at position 2: 1\̲2̲ 类棋子改为 X,所有第 KaTeX parse error: Undefined control sequence: \3 at position 2: 2\̲3̲ 类棋子改为 O 两种方案,总共三种方案,所需要更改的棋子数是将所有棋子全部改完所需要的次数。
根据抽屉原理,三种方案必定至少有一种方案需要的次数少于总棋子数的 1 3 \frac 1 3 31,所以分别统计需要更改个数,最后随意选择一种合理的方案更改即可。
AC code
#include<bits/stdc++.h>
using namespace std;
int T,n,numx[3],numo[3],sum,xz;
char ch[305][305];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n),sum=numx[0]=numx[1]=numx[2]=numo[0]=numo[1]=numo[2]=0;
for(int i=1;i<=n;++i)
{
scanf("%s",ch[i]+1);
for(int j=1;j<=n;++j)
{
if(ch[i][j]=='O') ++numo[(i+j)%3],++sum;
if(ch[i][j]=='X') ++numx[(i+j)%3],++sum;//记录每种方案需要更改的棋子数
}
}
if(numx[0]+numo[1]<=sum/3) xz=0;
if(numx[1]+numo[2]<=sum/3) xz=1;
if(numx[2]+numo[0]<=sum/3) xz=2;//判断使用那种方法
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(ch[i][j]=='.') printf(".");
else
{
if((i+j)%3!=xz&&(i+j)%3!=(xz+1)%3) printf("%c",ch[i][j]);
else
{
if((i+j)%3==xz) printf("O");
else printf("X");
}//对应更改即可
}
}
puts("");
}
}
return 0;
}
1万+



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



