P12529 [XJTUPC 2025] 对称隔离:黑白之战题解

· · 题解

思路

非常巧妙的思路!

我们可以对于每块地毯进行分析,分为四种情况:

我们将前三种情况的地毯分别标记为 012

然后判断是否有可能存在竖直或水平对称轴。

对于竖直对称的两块地毯,如果存在两块地毯标记不相同,且都不是 2,那就不存在竖直对称轴。

水平对称同理。

正确性证明

这时候就有人要说了,这不是瞎写吗?假设两块相邻的地毯都由白变黑,这怎么办?

我们来分析一下:

现在有一块地毯 X_1,它有一块相邻的地毯 Y_1

水平对称同理。 $X_1$ 和 $Y_1$ 不能都为黑。 那么 $X_2$ 和 $Y_2$ 都不能由白变黑。 相反同理。 所以只能是 $X_1$ 和 $Y_2$ 为黑,$X_2$ 和 $Y_1$ 为白,相反同理。 但是此时又不满足上面的假设了,$X_2$ 和 $Y_1$ 相邻的地毯有黑了,不能变色了。 所以这种思路是正确的。 # AC code ```cpp #include<bits/stdc++.h> using namespace std; const int N=105; int a[N][N],c[N][N]; string s; int pd(int x,int y){ if(!c[x][y]){ if(c[x-1][y]|c[x][y-1]|c[x+1][y]|c[x][y+1]) return 0; //这块地毯白,相邻的有黑 else return 2;//这块地毯白,相邻的地毯白 } else return c[x-1][y]|c[x][y-1]|c[x+1][y]|c[x][y+1]; } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>s; for(int j=1;j<=m;j++){ if(s[j-1]=='W') c[i][j]=0; else c[i][j]=1;//标记颜色 } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(pd(i,j)==1){//有相邻的黑色 cout<<"No"; return 0; } if(pd(i,j)==2) a[i][j]=2;//这块白地毯可改为黑色 else a[i][j]=c[i][j];//这块地毯不能改变颜色 } } //竖直对称轴 int vis=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]!=a[i][m-j+1] && a[i][j]!=2 && a[i][m-j+1]!=2){ vis=1;//两块地毯颜色不同且无法改变颜色 break; } } if(vis) break; } if(!vis){ cout<<"Yes"; return 0; } //水平对称轴 vis=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]!=a[n-i+1][j] && a[i][j]!=2 && a[n-i+1][j]!=2){ vis=1;//两块地毯颜色不同且无法改变颜色 break; } } if(vis) break; } if(!vis){ cout<<"Yes"; return 0; } cout<<"No";//两个对称轴都没有 } ```