【题目描述】

     给定一个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<<],col[maxn<<];
rec() {
sum=inf;
memset(topo,,sizeof topo);
memset(col,,sizeof col);
}
}ans; int n,m,k,l;
int a[maxn][maxn],judge[maxn<<],last[maxn<<],other[maxn*maxn],pre[maxn*maxn];
int cnt[maxn<<],que[maxn<<]; void connect(int x,int y) {
pre[++l]=last[x];
last[x]=l;
other[l]=y;
//printf("%d %d\n",x,y);
} bool topo() {
memset(cnt,,sizeof cnt);
memset(que,,sizeof que);
for (int i=;i<=n+m;i++)
for (int p=last[i];p;p=pre[p]) cnt[other[p]]++;
int h=,t=;
for (int i=;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\n",t);
return (t==n+m);
} void work(int x) {
memset(judge,-,sizeof judge);
memset(last,,sizeof last);
l=;
if (x<=n) {
for (int i=;i<=m;i++) judge[i+n]=a[x][i];
for (int i=;i<=n;i++) if (i!=x) {
for (int j=;j<=m;j++) if (judge[j+n]!=a[i][j]) {
if ((judge[i]!=-)&&(judge[i]!=a[i][j])) return ;
judge[i]=a[i][j];
if (!judge[i]) return ;
connect(j+n,i);
}
for (int j=;j<=m;j++) if ((judge[j+n]==a[i][j])&&(judge[j+n]!=judge[i])) connect(i,j+n);
}
} else {
for (int i=;i<=n;i++) judge[i]=a[i][x-n];
for (int i=;i<=m;i++) if (i+n!=x) {
for (int j=;j<=n;j++) if (judge[j]!=a[j][i]) {
if ((judge[i+n]!=-)&&(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=;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=;
for (int i=;i<=n+m;i++) if ((judge[i]!=-)&&(judge[i])) cur++;
if (cur<ans.sum) {
ans.sum=cur;
for (int i=;i<=n+m;i++) ans.topo[i]=que[i],ans.col[i]=judge[que[i]];
}
}
//printf("%d\n",x);
//for (int i=1;i<=n+m;i++) printf("%d ",judge[i]); printf("\n");
} int main() {
freopen("iridescent.in","r",stdin); freopen("iridescent.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++) scanf("%d",&a[i][j]);
for (int i=;i<=n+m;i++) work(i);
//work(51);
if (ans.sum==inf) printf("-1\n"); else {
printf("%d\n",ans.sum);
for (int i=;i<=n+m;i++) {
if (ans.col[i]==-) 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\n",ans.col[i]);
}
}
fclose(stdin); fclose(stdout);
return ;
}

【HNOI】五彩斑斓 模拟的更多相关文章

  1. CTSC2015&APIO2015滚粗记

    CTSC 这次CTSC的考试,觉得还是考出了自己该有的水平.虽然自己最后还是没有得到金牌,但是我觉得自己尽力了,也没有什么太大的遗憾.比起省选,自己在应试的方面又有了很大的进步. Day1是我主要捞分 ...

  2. 3194. 【HNOI模拟题】化学(无标号无根树计数)

    Problem 求\(n\)个点的每个点度数不超过\(4\)的无标号无根树个数. Data constraint \(1\le n\le 500\) Solution 尝试着把问题一般化.我们来考虑一 ...

  3. 【HNOI模拟By lyp】Day2

    1 toad1.1 题目描述 有 n 个石子, A B 两人博弈, A 先手. A 首先取若干个石子(至少一个,不能取完),然后B和A 再轮流取石子,每次取的石子不能超过 axb ( x 表示上次取的 ...

  4. 【HNOI模拟By lyp】Day1

    1 xlk1.1 题目描述 给定一棵大小为 n 的无根树,求满足以下条件的四元组 (a, b, c, d) 的个数: 1. 1 ≤ a < b ≤ n 2. 1 ≤ c < d ≤ n 3 ...

  5. 【HNOI模拟By YMD】move

    Description 设P(n)为从(0,0)移动到点(n,0)的不同路径数目,移动的方式有以下三种:(x,y)->(x+1,y-1),(x,y)->(x+1,y),(x+y)-> ...

  6. HNOI模拟 Day3.25 By Yqc

    怕老婆 [问题描述] 有一天hzy9819,来到了一座大城市拥有了属于他自己的一双滑板鞋.但是他还是不满足想要拥有属于自己的一栋楼,他来到了一条宽敞的大道上,一个一个记录着这些楼的层数以方便自己选择. ...

  7. HNOI模拟 Day3.23

    一.拓扑(top)[ 题目描述]:给你一个有向二分图,求他的拓扑序列的个数.[ 输入]:第一行两个数 N,M,表示点数和边数.接下来 M 行每行两个数 a,b,表示 a 向 b 有一条有向边.[ 输出 ...

  8. HNOI模拟 Day3.22

    第一题: 盾盾的打字机 (drdrd) [题目描述] 盾盾有一个非常有意思的打字机,现在盾哥要用这台打字机来打出一段文章. 由于有了上次的经验,盾盾预先准备好了一段模板 A 存在了内存中,并以此为基础 ...

  9. NOIP模拟赛 17.10.10

    初次见面(firstmeet)[题目背景]雾之湖边,静得可怕.露米娅出神凝望.黑白连衣裙,像极了绽放的墨黑和洁白的莲.身边的雾之湖,倒映着血色天空.酒红的双眸,映照一切.低声浅笑,双臂伸直,她悄无声息 ...

随机推荐

  1. idea dubbo jar error:cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 'dubbo:application' 的声明

    声明: 出现这个错误的情形是,在idea开发环境里面运行是没有问题的,使用哦idea自带的打包工具生成jar之后,运行jar的时候报的这个错误,如果不是这个情况,这篇文章可能不适用. 主要的原因是sp ...

  2. 【Docker 命令】- top命令

    docker top :查看容器中运行的进程信息,支持 ps 命令参数. 语法 docker top [OPTIONS] CONTAINER [ps OPTIONS] 容器运行时不一定有/bin/ba ...

  3. Windows API封装:LoadLibrary/FreeLibrary

    LoadLibrary/LoadLibraryEx用来加载DLL到自己的进程空间,使用完用FreeLibrary释放,一般使用方式如下:    HINSTANCE hInstRich = ::Load ...

  4. c++的一些编程技巧和细节

    1.函数形参,如: CreateProcess(                  NULL,                  cmdbuf,                  NULL,      ...

  5. BIO、NIO、AIO通信机制

    一.BIO的理解 首先我们通过通信模型图来熟悉下BIO的服务端通信模型:采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端的连接请求之后为每个客户端创 ...

  6. Ajax在jQuery中的应用(加载异步数据、请求服务器数据)

    加载异步数据 jQuery中的load()方法 load(url,[data],[callback]) url:被加载的页面地址 [data]:可选项表示发送到服务器的数据,其格式为 key/valu ...

  7. 【WCF】WCF 附录 高级主题 配置服务配额设置

    微软产品自带一个“默认安全”方案.这也包括了WCF,意味着WCF中的多种配置可以设置来阻止诸如DOS(拒绝服务访问)攻击.微软为很多基于一个单一计算机的开发环境选择这样的设置.这也意味着默认设置中的一 ...

  8. 【bzoj1030】[JSOI2007]文本生成器 AC自动机+dp

    题目描述 JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固 ...

  9. BZOJ4300 绝世好题(动态规划)

    设f[i][j]为前i个数中所选择的最后一个数在第j位上为1时的最长序列长度,转移显然. #include<iostream> #include<cstdio> #includ ...

  10. CodeForces - 704C

    题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 a 或者 a|b 亦或起来,每个变量最多出现两次(包括反变量) 嘴炮开始:每个变量最多出现两次,那么跟它相关联的变量 ...