zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第六场)G

    Description

    (n imes n) 的网格图的边染 (k) 种颜色,每种颜色染的边数相同,构造不存在同色环,且没有某一整行或整列的颜色相同的方案数。

    Solution

    约定左上角的格点为 ((0,0)),由一个点 ((i,j)) 向右发出的边记做 ((i,j,0)),向下发出的边记做 ((i,j,1))

    先考虑两种颜色时怎么放。

    (n) 为偶数,则选取 (0,0,0),(0,2,0),(0,4,0),...,(1,1,0),(1,3,0),(1,5,0),...,(2,0,0),(2,2,0),(2,4,0),...,...,(0,0,1),(0,1,1),(0,2,1),...,(2,0,1),(2,1,1),(2,2,1),...,...,...

    (n) 为奇数,则按 ((i,j,k))((i+j) mod 2) 定色。

    考虑 (k) 种颜色且 (k) 为偶数时,我们将原先的黑色中任意分出若干个给 ([k/2-1]) 种新颜色,将原先的白色中任意分出若干个给另外 ([k/2-1]) 种新颜色。

    (k) 为奇数时,我们需要分 (siz) 条边给多出来的那一种颜色,我们只需要从左半图中贪心地取若干条黑边,右半图中贪心地取若干白边,数量分别为 (frac {siz} {2}),然后再按 (k) 为偶数的情况继续执行即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 205;
    int f[N][N][2];
    
    void solve(int n,int k)
    {
        // Step 0
        for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f[i][j][0]=f[i][j][1]=0;
        for(int i=0;i<=n;i++) f[n][i][1]=f[i][n][0]=-1;
        
        // Step 1
        if(n&1)
        {
            for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=0;k<2;k++) if(f[i][j][k]!=-1) f[i][j][k]=(i+j+1)%2;
        }
        else
        {
            for(int i=0;i<=n;i++) for(int j=i&1;j<n;j+=2) f[i][j][0]=1;
            for(int i=0;i<n;i+=2) for(int j=0;j<=n;j++) f[i][j][1]=1;
        }
    
        // Step 2
        if(k&1)
        {
            int c=k-1,tot=2*n*(n+1)/k,cnt=0;
            for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=1;k>=0;k--) if(f[i][j][k]==0 && cnt<tot/2) f[i][j][k]=c, ++cnt;
            for(int i=n;i>=0;i--) for(int j=n;j>=0;j--) for(int k=1;k>=0;k--) if(f[i][j][k]==1 && cnt>0) f[i][j][k]=c, --cnt;
        }
    
        // Step 3
        if(k>2)
        {
            int t=(k-2)/2,cnt=0,siz=2*n*(n+1)/k;
            for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=1;k>=0;k--)
            {
                int c=2+cnt/siz;
                if(c<=2+t-1)
                {
                    if(f[i][j][k]==0) f[i][j][k]=c,++cnt;
                }
            }
            for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=1;k>=0;k--)
            {
                int c=2+cnt/siz;
                if(c<=2+2*t-1)
                {
                    if(f[i][j][k]==1) f[i][j][k]=c,++cnt;
                }
            }
        }
        
        // Output
        for(int i=0;i<=n;i++) 
        {
            for(int j=0;j<n;j++) printf("%d ",f[i][j][0]+1);
            puts("");
        }
        for(int i=0;i<=n;i++) 
        {
            for(int j=0;j<n;j++) printf("%d ",f[j][i][1]+1);
            puts("");
        }
    
        
    }
    
    int T,n,k;
    
    bool TP()
    {
        if(n==1||k<=1||2*(n+1)*n%k!=0)
        {
            printf("-1
    "); 
            return true;
        }
        if(n==2&&k==3)
        {
            printf("1 2
    ");
            printf("3 1
    ");
            printf("3 2
    ");
            printf("1 3
    ");
            printf("2 1
    ");
            printf("2 3
    ");
            return true;
        }
        if(n==3&&k==3)
        {
            printf("1 2 3
    ");
            printf("2 3 2
    ");
            printf("1 3 1
    ");
            printf("3 1 2
    ");
            printf("3 2 1
    ");
            printf("3 1 2
    ");
            printf("1 2 3
    ");
            printf("2 1 3
    ");
            return true;
        }
        return false;
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&k);
            if(!TP()) solve(n,k);
        }
        return 0;
    }
    
    // Checker
        /*map<int,int> mp;
        for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) 
        {
            mp[f[i][j][0]]++;
            mp[f[i][j][1]]++;
        }
        int siz=2*n*(n+1)/k;
        for(auto i:mp) if(i.first>=0) if(i.second!=siz) cout<<"FAILED A"<<endl;
    
        for(int i=0;i<=n;i++) for(int j=0;j<=n;j++)
        {
            if(f[i][j][0]==f[i][j+1][0] && j+1<=n) cout<<"FAILED B"<<endl;
            if(f[i][j][1]==f[i+1][j][1] && i+1<=n) cout<<"FAILED B"<<endl;
        }
    
        for(int i=0;i<n;i++) for(int j=0;j<n;j++)
        {
            set<int> s;
            s.insert(f[i][j][0]);
            s.insert(f[i][j][1]);
            s.insert(f[i+1][j][0]);
            s.insert(f[i][j+1][1]);
            if(s.size()==1) cout<<"FAILED C"<<endl;
        }*/
    
  • 相关阅读:
    leetcode题库
    递归的存储以及执行顺序
    linux与开发板串口通信
    opencv基础到进阶(2)
    opencv基础到进阶(1)
    js的搜索遍历精讲
    js闭包深度讲解
    js使用for in遍历时的细节问题
    分分钟解决正则表达式
    css3中的新特性经典应用
  • 原文地址:https://www.cnblogs.com/mollnn/p/13773810.html
Copyright © 2011-2022 走看看