牛客多校第六场 Grid Coloring(染色,构造)

牛客多校第六场 Grid Coloring(染色,构造)_第1张图片

题意:
n ∗ n n*n nn的格子, k k k种颜色。
给每条边染色,要求

  1. 不存在一行或一列颜色相同
  2. 不存在同色环
  3. 各种颜色使用的数目相同

思路:
特判一下无解的情况 n = = 1 ∣ ∣ k = = 1 ∣ ∣ 2 ∗ ( n + 1 ) ∗ n m o d    k    ! = 0 n == 1 || k == 1 || 2 * (n + 1) * n \mod k\; != 0 n==1k==12(n+1)nmodk!=0
其他情况有解。
每一行从左到右顺序染色,从左到右对竖边染色,从上到下执行这个过程。
这样可以保证每一行不相同,左右相邻两竖边颜色不同。
这样肯定不存在同色环和同颜色的一行。

但是这样每一列相邻两边的颜色间隔为 2 ∗ n + 1 2*n+1 2n+1,也就是当满足 k ∣ ( 2 ∗ n + 1 ) k|(2*n+1) k(2n+1)时,可能出现列的颜色相同。所以我们特判这种情况,当染竖直边的时候,对于奇数行下面的竖直边,往右循环一位染色。

#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 205;
vector<int>H[maxn],V[maxn];
int n,k;

void Print() {
    for(int i = 1;i <= n + 1;i++) {
        for(int j = 0;j < H[i].size();j++) {
            printf("%d ",H[i][j]);
        }
        printf("\n");
    }
    
    for(int i = 1;i <= n + 1;i++) {
        for(int j = 0;j < V[i].size();j++) {
            printf("%d ",V[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n + 1;i++) {
            H[i].clear();V[i].clear();
        }
        if(n == 1 || k == 1 || 2 * (n + 1) * n % k != 0) {
            printf("-1\n");
        } else {
            int now = 0;
            for(int i = 1;i <= n + 1;i++) {
                for(int j = 1;j <= n;j++) {
                    H[i].push_back(now + 1);
                    now = (now + 1) % k;
                }
                if(i != n + 1) {
                    for(int j = 1;j <= n + 1;j++) {
                        int nex = j;
                        if((2 * n + 1) % k == 0 && (i & 1)) { //当满足这个情况的时候,将偶数行下面列的颜色循环右移一位,保证一列不相同
                            nex = nex % (n + 1) + 1;
                        }
                        V[nex].push_back(now + 1);
                        now = (now + 1) % k;
                    }
                }
            }
            Print();
        }
    }
    return 0;
}

你可能感兴趣的:(思维构造,#,其他比赛题目)