CF1586I 题解

发布时间 2023-10-26 20:35:04作者: Xttttr

CF1586I 题解


传送门


更好的阅读体验


简化题意:有 $n\times n$ 的网格,你需要进行黑白染色,使得每个格子的颜色恰好与 2 个与其四联通的格子的颜色相同,其中有些位置已经确定,问是否有解及是否有唯一解。

思路:


很神仙的构造题。

先从特殊的地方入手。对于 4 个角,它们只和 2 个格子相邻,因此颜色也必须相同。接着考虑与主对角线相邻的两条对角线,我们可以从边界上入手,边界上的两个格子颜色必须相同,而对于主对角线上的第二个格子,现在已经有两个相邻格子是一个颜色了,因此剩下的两个格子颜色一定与刚刚的两个格子不同,于是可以推出这两条对角线上的格子的颜色是黑白交替的,如下图(图都是搬运自 CF 官方题解 ):



考虑到这和奇偶性有关,可以分析一下 $n$ 的奇偶性。发现当 $n$ 为奇数时,主、副对角线相邻的各两条对角线会在中心的边上重合,但是两边都得是黑黑白交替的,无法同时满足,因此必然无解。

接着考虑另一个方向的对角线,如下图的黄色部分:


对于在左边界上的蓝色格子,我们已经知道它下面的格子和它一个颜色了,因此与它相邻的两个黄色格子颜色一定不同,于是可以推出黄色的格子颜色也是黑白交替的。又因为这条对角线的长度是奇数,因此在边界上的两个格子颜色相同。而这两个格子颜色相同也可以推出下图中红色格子颜色相同:


于是可以推出两个红色的格子所在对角线是相同的,且都是黑白交替的:


这样不断拓展下去可以推出整个图形是关于主、副对角线对称的。

然后是关键一步:对于下图中上面那个红色格子,与其相邻的两个黄色格子只会有一个的颜色与它相同,于是下面的格子也一定是红色,


那么继续拓展下去可以知道,我们把边界上的格子两两一组,每一组格子的颜色一定相同:


再根据之前与对角线相关的结论,我们可以知道每一组格子会对应哪些对角线,于是我们就知道了每个格子会影响哪些格子:


具体地,对于相同颜色的格子,在边界上黑白应该相同,在对角线上应该黑白交替。这样我们相当于是把每个格子的限制转到了对边界的限制,于是我们就很容易求出答案了。

代码:
点击查看代码
inline void solve(){
    cin>>n;
    for(int i=0;i<n;i++)cin>>c[i];
    if(n&1){
        cout<<"NONE";
        return;
    }
    for(int i=0;i<n;i++){
        if(i&1){
            for(int j=i;j<n;j++)id[j][j-i]=id[j-i][j]=id[n-1-j][n-1-(j-i)]=id[n-1-(j-i)][n-1-j]=i^1;
        }
        else for(int j=i;~j;j--)id[j][i-j]=id[i-j][j]=id[n-1-j][n-1-(i-j)]=id[n-1-(i-j)][n-1-j]=i;
    }
    memset(ans,-1,sizeof(ans));
    for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(c[i][j]!='.'){
        bool fl=c[i][j]=='G';
        if(i&&i<n-1&&j&&j<n-1)fl^=(min({i,j,n-1-i,n-1-j})&1);
        if(!~ans[id[i][j]])ans[id[i][j]]=fl;
        else if(ans[id[i][j]]!=fl){
            cout<<"NONE"<<endl;
            return;
        }
    }
    for(int i=0;i<n;i+=2)if(!~ans[i]){
        cout<<"MULTIPLE"<<endl;
        return;
    }
    cout<<"UNIQUE"<<endl;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            bool fl=ans[id[i][j]];
            if(i&&i<n-1&&j&&j<n-1)fl^=(min({i,j,n-1-i,n-1-j})&1);
            cout<<(fl?'G':'S');
        }
        cout<<endl;
    }
}