zoukankan      html  css  js  c++  java
  • 【HNOI】五彩斑斓 模拟

      【题目描述】

         给定一个n*m的矩阵,矩阵的某些位置有一个颜色(可以没有颜色,即为0),现在你可以将矩阵的某一行或者某一列染成同一种颜色,问最少用多少步能达到目标矩阵的染色方案,输出最少步数和方案。

      【数据范围】

        n,m<=50。颜色数<=60。

      首先我们贪心的知道,矩阵的每一行/列最多会被染色一次,所以染色的目前的上限是n+m。而且每染一次,肯定至少减少矩阵的一行/一列,最坏情况下,其中一次染色的贡献只有1*1的矩阵,对于这个1*1的矩阵,我们不必染两次,所以染色的上限其实是n+m-1。

      这样我们知道肯定有其中某一行(列情况类似)没有被染色,那么我们枚举这一行,那么我们可以根据这个没有染色的得出与该行相交的列的染色情况,那么我们现在知道了所有的列的染色情况,我们再枚举每一行,通过这一行的其余颜色可以判定这一行的颜色或者是否合法,而且我们根据这一行与已知列相交的地方的颜色,我们可以得到该行与每一列染色的前后顺序,如果顺序组成的图是DAG就说明有解,且需要染色的行/列就是答案,取最优就好了。

      反思:开始对于某一行和已知列颜色相同的时候觉得不需要特判,所以就直接让一个在另一个前,这样其实是不行的,他们之间应该不连边,代表没有顺序要求。 

         写没有染色的地方的时候没有特判,最后程序跑的是0可以被当做一种颜色染,然后就跪了。

         写列的时候照着行写的,结果好几个地方不一样也没改,然后又跪了= =。

    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #define maxn 60
    #define inf (~0U>>1)
    
    using namespace std;
    
    struct rec {
        int sum;
        int topo[maxn<<1],col[maxn<<1];
        rec() {
            sum=inf;
            memset(topo,0,sizeof topo);
            memset(col,0,sizeof col);
        }
    }ans;
    
    int n,m,k,l;
    int a[maxn][maxn],judge[maxn<<1],last[maxn<<1],other[maxn*maxn],pre[maxn*maxn];
    int cnt[maxn<<1],que[maxn<<1];
    
    void connect(int x,int y) {
        pre[++l]=last[x];
        last[x]=l;
        other[l]=y;
        //printf("%d %d
    ",x,y);
    }
    
    bool topo() {
        memset(cnt,0,sizeof cnt);
        memset(que,0,sizeof que);
        for (int i=1;i<=n+m;i++)
            for (int p=last[i];p;p=pre[p]) cnt[other[p]]++;
        int h=0,t=0;
        for (int i=1;i<=n+m;i++) if (!cnt[i]) que[++t]=i;
        while (h<t) {
            int cur=que[++h];
            for (int p=last[cur];p;p=pre[p]) {
                cnt[other[p]]--;
                if (!cnt[other[p]]) que[++t]=other[p];
            }
        }
        //printf("%d
    ",t);
        return (t==n+m);
    }
    
    void work(int x) {
        memset(judge,-1,sizeof judge);
        memset(last,0,sizeof last);
        l=0;
        if (x<=n) {
            for (int i=1;i<=m;i++) judge[i+n]=a[x][i];
            for (int i=1;i<=n;i++) if (i!=x) {
                for (int j=1;j<=m;j++) if (judge[j+n]!=a[i][j]) {
                    if ((judge[i]!=-1)&&(judge[i]!=a[i][j])) return ;
                    judge[i]=a[i][j];
                    if (!judge[i]) return ;
                    connect(j+n,i);
                }
                for (int j=1;j<=m;j++) if ((judge[j+n]==a[i][j])&&(judge[j+n]!=judge[i])) connect(i,j+n);
            }
        } else {
            for (int i=1;i<=n;i++) judge[i]=a[i][x-n];
            for (int i=1;i<=m;i++) if (i+n!=x) {
                for (int j=1;j<=n;j++) if (judge[j]!=a[j][i]) {
                    if ((judge[i+n]!=-1)&&(judge[i+n]!=a[j][i])) return ;
                    judge[i+n]=a[j][i];
                    if (!judge[i+n]) return ;
                    connect(j,i+n);
                } 
                for (int j=1;j<=n;j++) if ((judge[j]==a[j][i])&&(judge[j]!=judge[i+n])) connect(i+n,j);
                //else connect(i+n,j);
            }
        }
        if (topo()) {
            int cur=0;
            for (int i=1;i<=n+m;i++) if ((judge[i]!=-1)&&(judge[i])) cur++;
            if (cur<ans.sum) {
                ans.sum=cur;
                for (int i=1;i<=n+m;i++) ans.topo[i]=que[i],ans.col[i]=judge[que[i]];
            }
        }
        //printf("%d
    ",x);
        //for (int i=1;i<=n+m;i++) printf("%d ",judge[i]); printf("
    ");
    }
    
    
    int main() {
        freopen("iridescent.in","r",stdin); freopen("iridescent.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
        for (int i=1;i<=n+m;i++) work(i);
        //work(51);
        if (ans.sum==inf) printf("-1
    "); else {
            printf("%d
    ",ans.sum);
            for (int i=1;i<=n+m;i++) {
                if (ans.col[i]==-1) continue;
                if (!ans.col[i]) continue;
                if (ans.topo[i]>n) printf("C %d",ans.topo[i]-n); else printf("R %d",ans.topo[i]);
                printf(" %d
    ",ans.col[i]);
            }
        }
        fclose(stdin); fclose(stdout);
        return 0;
    }
  • 相关阅读:
    MVC ORM 架构
    Kubernetes 第八章 Pod 控制器
    Kubernetes 第七章 Configure Liveness and Readiness Probes
    Kubernetes 第六章 pod 资源对象
    Kubernetes 第五章 YAML
    Kubernetes 核心组件
    Kubernetes 架构原理
    Kubernetes 第四章 kubectl
    Kubernetes 第三章 kubeadm
    yum 配置及yum 源配置
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3635442.html
Copyright © 2011-2022 走看看