题意:
对一个$n$行$m$列的网格黑白染色,满足:
1.黑色的格子两两四联通,白色格子两两四联通,且黑色的格子经过旋转和平移可以和白色的格子重合
2.$w(wx,wy)$这个格子是白色的,$b(bx,by)$这个格子是黑色的。
要求找到任意一个解,或者判断无解。多组数据。
$1le Tle 10^3, ;1le n,mle 50, ;1le wx,bxle n, ; 1le wy,byle m ,; (wx,wy) eq(bx,by)$
分析:
首先考虑什么时候无解。
①网格数为奇数,无法均分
②仅有单行/单列且指定黑白格在同侧,也无法均分
接下来分类讨论:
①若$2|m$(可通过整张图旋转$90^{circ}$得到,下同),且两个指定点分居中线两侧,则直接对切。
②若指定点居于中线同侧,且在不同行,可如上图染色。
③若指定点居于中线异侧,且在相同行,离中线近的指定点不在最后一行,可如上图染色。
实现(100分):
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define IL inline #define UI unsigned int #define RI register int using namespace std; const int N=50; IL void swap(int &x,int &y){ int t=x; x=y; y=t; } int T,n,m,wx,wy,bx,by; bool flag1,flag2,flag3,flag4; int nn,mm,c,d,x[2],y[2]; int bod[N+3][N+3]; IL void step1(){ if(n*m%2==1){ flag1=true; return ; } x[0]=wx; y[0]=wy; x[1]=bx; y[1]=by; if(m%2==1){ flag2=true; swap(n,m); for(int i=0;i<2;i++) swap(x[i],y[i]); } mm=m/2; if(n==1&&((y[0]<=mm&&y[1]<=mm)||(y[0]>mm&&y[1]>mm))){ flag1=true; return ; } } IL bool cmp1(){ if(y[0]==y[1]) return x[0]<x[1]; return y[0]<y[1]; } IL bool cmp2(){ if(x[0]==x[1]) return y[0]<y[1]; return x[0]<x[1]; } IL void sol1(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) bod[i][j]=(j<=mm)?c:d; } IL void sol2(){ int vx[2]; for(int i=0;i<2;i++) vx[i]=n-x[i]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) bod[i][j]=(i<=(j<=mm?x[c]:vx[c]))?c:d; } IL void sol3(){ int vx[2]; for(int i=0;i<2;i++) vx[i]=n-x[i]+1; int vy[2]; for(int i=0;i<2;i++) vy[i]=m-y[i]+1; memset(bod,-1,sizeof bod); for(int i=1;i<=x[d];i++) for(int j=y[d];j<=mm;j++) bod[i][j]=d; for(int i=vx[d];i<=n;i++) for(int j=mm+1;j<=vy[d];j++) bod[i][j]=c; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(!~bod[i][j]) bod[i][j]=(j<=mm)?c:d; } IL void step2(){ c=cmp1()?0:1; d=c^1; if(y[c]<=mm&&y[d]>mm){ sol1(); return ; } if(y[c]>mm){ flag3=true; for(int i=0;i<2;i++) y[i]=m-y[i]+1; c=cmp1()?0:1; d=c^1; } if(x[d]==n){ flag4=true; for(int i=0;i<2;i++) x[i]=n-x[i]+1; } c=cmp2()?0:1; d=c^1; if(x[c]!=x[d]) sol2(); else sol3(); } IL void step3(){ if(flag4) for(int i=1,ti=n;i<ti;i++,ti--) for(int j=1;j<=m;j++) swap(bod[i][j],bod[ti][j]); if(flag3) for(int i=1;i<=n;i++) for(int j=1,tj=m;j<=mm;j++,tj--) swap(bod[i][j],bod[i][tj]); if(flag2){ int tmp[N+3][N+3]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) tmp[j][i]=bod[i][j]; memcpy(bod,tmp,sizeof bod); swap(n,m); } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) printf("%d ",bod[i][j]); printf(" "); } } int main(){ freopen("A.in","r",stdin); freopen("A.out","w",stdout); scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d%d",&n,&m,&wx,&wy,&bx,&by); flag1=flag2=flag3=flag4=false; step1(); if(flag1){ printf("-1 "); continue; } step2(); step3(); } return 0; }
小结:
简洁分类,转化简并。