题目

给你一个\(n \times m\)的01矩阵

你需要用一些矩阵加减出这个矩阵

求最少的步数,并输出方案

需要满足构造出的01矩阵是一个四联通块

$ n\ , \ m \le 500 $

题解

  • 答案=0/1/2时特判,n,m<=2时特判

  • 如何用三步构造一个$ n \le m \ , m \ge 3$的矩阵

    矩阵A:

    第1列为1,奇数行为1,偶数行为原矩阵

    矩阵B:

    第n列为1,偶数行为1,奇数行为原矩阵

    矩阵C:

    第一列和最后一列为原矩阵取反,其它为0

    用A+B-C即可构造

Code

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=510;
int n,m,a[N][N],rev,b[N][N],f[N*N],tot,vis[N*N],id[N][N],st1[N*N],t1,st2[N*N],t2;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
vector<int>vec[N*N];
char s[N];
void print(){
if(!rev){
for(int i=1;i<=n;++i,puts(""))
for(int j=1;j<=m;++j)printf("%d",b[i][j]);
}else{
for(int i=1;i<=m;++i,puts(""))
for(int j=1;j<=n;++j)printf("%d",b[j][i]);
}
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void uni(int x,int y){
if(!x||!y)return;
int fx=find(x),fy=find(y);
if(fx==fy)return;
f[fx]=fy;
}
int main(){
freopen("bitbit.in","r",stdin);
freopen("bitbit.out","w",stdout);
scanf("%d%d",&n,&m);
int ex=0;
for(int i=1;i<=n;++i){
scanf("%s",s+1);
for(int j=1;j<=m;++j)a[i][j]=s[j]=='1',ex|=a[i][j];
}
if(!ex)puts("0"),exit(0);
if(n>m){
for(int i=1;i<=n;++i)
for(int j=1;j<=i&&j<=m;++j){
swap(a[i][j],a[j][i]);
}
swap(n,m);rev^=1;
}
if(n==1){
int ans=0;
for(int i=1;i<=m;++i)if(a[1][i]&&a[1][i]!=a[1][i-1])ans++;
printf("%d\n",ans);
for(int i=1;i<=m;++i)if(a[1][i]){
puts("+");
for(int j=1;j<i;++j)b[1][j]=0;
for(;i<=m&&a[1][i];++i)b[1][i]=1;
for(int j=i--;j<=m;++j)b[1][j]=0;
print();
}
return 0;
}//n=1||m=1
if(n==2&&m==2){
int tmp=a[1][1]+a[1][2]+a[2][1]+a[2][2];
if(tmp==2&&max(a[1][1]+a[2][2],a[1][2]+a[2][1])==2){
puts("2");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)if(a[i][j]){
puts("+");
for(int i1=1;i1<=n;++i1)
for(int j1=1;j1<=m;++j1)
b[i1][j1]=(i1==i&&j1==j);
print();
}
return 0;
}//ans=2
puts("1");
puts("+");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)b[i][j]=a[i][j];
print();//ans=1;
return 0;
}//n=2&&m=2
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)id[i][j]=++tot,f[tot]=tot;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(a[i-1][j]==a[i][j])uni(id[i-1][j],id[i][j]);
if(a[i][j-1]==a[i][j])uni(id[i][j-1],id[i][j]);
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
vec[find(id[i][j])].pb(id[i][j]);
if(f[id[i][j]]!=id[i][j])continue;
if(a[i][j])st1[++t1]=id[i][j];
else st2[++t2]=id[i][j];
}
if(t1<=2){
printf("%d\n",t1);
for(int I=1;I<=t1;++I){
puts("+");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)b[i][j]=(f[id[i][j]]==st1[I]);
print();
}
return 0;
}//ans=1,ans=2(1)
for(int I=1;I<=t2;++I){
for(int pos : vec[st2[I]]){
int x=(pos-1)/m+1,y=(pos-1)%m+1;
for(int k=0;k<4;++k){
int nx=x+dx[k],ny=y+dy[k];
if(id[nx][ny])vis[f[id[nx][ny]]]=I;
}
}
int fg=1;for(int i=1;i<=t1;++i)if(vis[st1[i]]!=I){fg=0;break;}
if(fg){
int now=st2[I];
puts("2");
puts("+");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)b[i][j]=(a[i][j])||(f[id[i][j]]==now);
print();
puts("-");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)b[i][j]=(f[id[i][j]]==now);
print();
return 0;
}
}//ans=2(2);
puts("3");
puts("+");
for(int i=1;i<=n;++i)
for(int j=1;j<m;++j)b[i][j]=(j==1)||(i&1)||(a[i][j]);
for(int i=1;i<=n;++i)b[i][m]=0;
print();
puts("+");
for(int i=1;i<=n;++i)
for(int j=2;j<=m;++j)b[i][j]=(j==m)||(!(i&1))||(a[i][j]);
for(int i=1;i<=n;++i)b[i][1]=0;
print();
puts("-");
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)b[i][j]=(j!=1&&j!=m)||(!a[i][j]);
print();//ans=3
return 0;
}

【JZOJ6236】【20190628】启程的日子的更多相关文章

  1. 【Objective-C基础教程-读书笔记】第1章 启程

    在第1章里面,作者主要以一种站在世界中心呼唤爱的姿态,给读者们打打鸡血洗洗脑,鼓励大家,投入时间学习Objective-C,值得啊! 首先,Objective-C既能用来开发OS X平台上的APP,又 ...

  2. 技术之美[程序人生]我在IBM实习的日子

    写这篇文章的时候,我已经在IBM正式工作了,看看上一篇博文的发布日期,才发现,我已经将近三个月没有更新博客了,多么惊人!为什么这么久?期间发生了很多事情.最重要的一件就是我大学毕业了!毕业的那么平淡, ...

  3. 开放才能进步!Angular和Wijmo一起走过的日子

    Angular 已成为广受欢迎的前端框架.去年9月份,期待已久的 Angular2 的正式版发布之后,Angular 又迎来了新一轮热潮.伴随着 Angular 这一路走来,Wijmo 一直都是第一个 ...

  4. 在没有DOM操作的日子里,我是怎么熬过来的(上)

    前言 在我动笔写这篇文章的时候,我刚刚从我的项目中删除了最后一行JQuery代码.至于我为何要这么做,请听闰土娓娓道来.前几年我还在想,假如有一天,前端世界里不能再直接操作dom了,我该怎么办?没想到 ...

  5. 在没有DOM操作的日子里,我是怎么熬过来的(终结篇)

    前言 在我写终结篇的日子里,Vue版本稳定在2.9.1.当我摸清Vue的脉络之后,以一个爬坑无数的亲历者的身份,谈谈我在MVVM时代里遇到的那些事儿. 接下来,正文从这开始~ 好多童鞋学习Vue都有灯 ...

  6. mxgraph进阶(四)mxGraph再启程

    mxgraph进阶(四)mxGraph再启程 前言   小论文Constructing User Interaction Behaviors Net from System Log. (AICE 20 ...

  7. 展开被 SpringBoot 玩的日子 《 五 》 spring data jpa 的使用

    在上篇文章< 展开被 SpringBoot 玩的日子 < 二 >WEB >中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring da ...

  8. 2018-04-10 我的GitHub诞生的日子,欢迎大家吐槽批评

    我的GitHub,诞生的日子,欢迎大家吐槽与批评,嘻嘻 首先是自己想刷一下LeetCode上的代码,其次创建了自己的读书笔记以及面试经验与教训 下边是仓库的Git链接,欢迎大家的批评与修正,谢谢: L ...

  9. 软件工程启程篇章:C#和四则运算生成与运算

    0x01 :序言 I leave uncultivated today, was precisely yestoday perishes tomorrow which the person of th ...

随机推荐

  1. Docker底层原理介绍

    1.docker介绍 1.1什么是docker Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻 ...

  2. [转帖]CHROME开发者工具的小技巧

    CHROME开发者工具的小技巧 https://coolshell.cn/articles/17634.html 需要仔细学习看一看呢. 2017年01月19日 陈皓 评论 58 条评论  64,08 ...

  3. Oppo Reno2 不允许安装非正式签名应用

    一.背景 为了安全起见,开发者本地开发和Jenkins上正式构建时,App采取的签名文件是不一样的.本地开发采取通用的如debug.keystore,正式签名文件部署在服务端.现在不少机型,如Oppo ...

  4. Logstash跟es加密通信

    前提条件,es集群内部各节点已开启https访问,集群也已开启x-pack安全功能,并设置了系统默认的用户密码等,具体操作详见:https://www.cnblogs.com/sanduzxcvbnm ...

  5. Java 线程的基本使用

    GitHub Page: http://blog.cloudli.top/posts/Java-线程的基本使用/ 创建线程 创建线程的方式有两种: 继承 Thread 类 实现 Runnable 接口 ...

  6. contos7自启动django服务

    研究了很多种办法 1.新建一个sh 文件 vi django_autostart.sh 2.编辑文件内容 #!/bin/bash #chkconfig:345 61 61 //此行的345参数表示,在 ...

  7. 从零开始一步一步搭建Ubuntu Server服务器、修改数据源、安装Docker、配置镜像加速器、Compose部署Gitlab服务

    场景 最终目的是使用Docker Compose部署一个Gitlab服务. 效果 注: 博客: https://blog.csdn.net/badao_liumang_qizhi关注公众号 霸道的程序 ...

  8. 2019-09-16 http 和 https的区别

    一.Http和Https的基本概念 Http:超文本传输协议(Http,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.设计Http最初的目的是为了提供一 ...

  9. web的应用模式

    在开发web应用中,有两种模式: 1.前后端分离. 2.前后端不分离. 一.前后端不分离 在前后端不分离的应用模式中,前端页面看到的效果是有后端控制的,由后端渲染页面或重定向,也就是后端需要控制前端的 ...

  10. Nginx实现防盗链的方式

    一.ngx_http_referer_module(阻挡来源非法的域名请求),配置如下: location ~.*\. (gif|jpg|png|flv|swf|rar|zip)$ { valid_r ...