题解:P12578 [UOI 2021] 彩色矩阵
题意
给定一个
要求不存在两个颜色相同的单元格,且它们之间的曼哈顿距离等于
两个单元格
请找到所需的最少颜色数量,并输出着色后的网格。其中
题解
这道题明显是一道构造题,看一下我们如何构造它:
有一个明显的情况是:当
接下来
我们只需要保证这个边界上的点都和中心点不同即可。
在众多尝试以后,我们可以发现以下只需要4种颜色的构造方法:
其中每个小正方形的对角线长度为
至于为什么,大家可以手玩一下,证明是显然的。代码实现估计大家都不一样,但还是贴一下代码。
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m,k,cnt,mo[N][N],mp[N][N],col;
int main(){
cin>>n>>m>>k;
if(k%2==1){
if(n==m&&m==1){cout<<1<<'\n'<<0;return 0;}
cout<<2<<'\n';
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if((i+j)%2==1) cout<<0<<" ";
else cout<<1<<" ";
}cout<<'\n';
}return 0;
}
cout<<4<<'\n';
for(int i=1;i<=k/2;i++){
for(int j=1;j<=k/2;j++){
if(i>=j) mo[i][j]=3;
}
for(int j=k/2+1;j<=k;j++){
mo[i][j]=mo[i][k-j+1];
if(mo[i][j]==3) mo[i][j]=1;
}
}
for(int i=k/2+1;i<=k;i++){
for(int j=1;j<=k/2;j++){
mo[i][j]=mo[i-k/2][j+k/2];
if(mo[i][j]) mo[i][j]=2;
else mo[i][j]=3;
}
for(int j=k/2+1;j<=k;j++){
mo[i][j]=mo[i-k/2][j-k/2];
if(mo[i][j]) mo[i][j]=2;
else mo[i][j]=1;
}
}
for(int i=1;i<=k;i++){
for(int j=k+1;j<=k*2;j++){
mo[i][j]=mo[i][2*k-j+1];
if(mo[i][j]==2) mo[i][j]=0;
else if(mo[i][j]==0) mo[i][j]=2;
}
}
for(int i=k+1;i<=2*k;i++){
for(int j=1;j<=k;j++){
mo[i][j]=mo[i-k][j+k];
}
for(int j=k+1;j<=k*2;j++){
mo[i][j]=mo[i-k][j-k];
}
}//实现上述最小单元的构造
k*=2;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<mo[(i-1)%k+1][(j-1)%k+1]<<" ";
}cout<<'\n';
}
return 0;
}