题目链接:传送门
题目大意:
给一个方阵,由 O X . , 构成,定义操作:可以将X改为O 或者把O 改成X,
设 O X 的数量为k ,操作次数不能超过 k/3 次 (向下取整);
最后输出方阵,满足横纵方向不存在连续三个X或O。
题目思路:
对于(i+j)%3==x 的单元格改为X ,(i+j+1)%3==x 的单元格改为O , 其中 x ∈ [0,3) ;
前者保证一定不存在有O 连成三个,后者保证一定不存在有X 连成三个。(保证行列中作为“阻隔”的X和O相互错开)
cnt_X + cnt_O = k ,
设 x 对应的修改次数为 y(x) , 有 y(1) + y(2) + y(3) = k ( 将三种情况并起来就是 (i+j)%3==0,1,2 的所有X改为O ,O改为X)
那么显然有,y(x)min≤ floor(k/3) ;
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 typedef unsigned long long uLL; 5 typedef pair<int,int> pii; 6 typedef pair<LL,LL> pLL; 7 typedef pair<double,double> pdd; 8 const int N=3e2+5; 9 const int M=1e7+5; 10 const int inf=0x3f3f3f3f; 11 const LL mod=998244353; 12 const double eps=1e-8; 13 const long double pi=acos(-1.0L); 14 #define ls (i<<1) 15 #define rs (i<<1|1) 16 #define fi first 17 #define se second 18 #define pb push_back 19 #define eb emplace_back 20 #define mk make_pair 21 #define mem(a,b) memset(a,b,sizeof(a)) 22 LL read() 23 { 24 LL x=0,t=1; 25 char ch; 26 while(!isdigit(ch=getchar())) if(ch=='-') t=-1; 27 while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } 28 return x*t; 29 } 30 char a[N][N],b[N][N][3]; 31 int cnt[3]; 32 int main() 33 { 34 int T=read(); 35 while(T--) 36 { 37 int n=read(); 38 for(int i=1;i<=n;i++) scanf("%s",a[i]+1); 39 for(int k=0;k<3;k++) 40 { 41 cnt[k]=0; 42 for(int i=1;i<=n;i++) 43 for(int j=1;j<=n;j++) 44 { 45 b[i][j][k]=a[i][j]; 46 if((i+j)%3==k&&b[i][j][k]=='X') b[i][j][k]='O',cnt[k]++; 47 else if((i+j+1)%3==k&&b[i][j][k]=='O') b[i][j][k]='X',cnt[k]++; 48 } 49 } 50 int ans=0; 51 for(int i=0;i<3;i++) if(cnt[ans]>cnt[i]) ans=i; 52 53 for(int i=1;i<=n;i++) 54 { 55 for(int j=1;j<=n;j++) putchar(b[i][j][ans]); 56 putchar(' '); 57 } 58 } 59 return 0; 60 }