noi.ac NA529 【神树的矩阵】
表示今天一发A了这题拿了rk3...是个sb构造...
考虑除了\(n=1/m=1\)的情况,最小次数\(ans\)不会\(>3\)。
对于\(n=1/m=1\),暴力即可。
然后考虑\(ans=0\),只有在图中没有\(1\)时成立。
对于\(ans=1\),图中的\(1\)是一个四联通块
对于\(ans=2\),加入图中的某个\(0\)的四联通块后所有的\(1\)是一个四联通块。
对于其他的情况,若\(\max(n,m)<3\),显然只有\(n=m=2\),枚举\(16\)种情况发现\(ans\leq 2\)。
所以考虑有\(\max(n,m)\geq 3\),此时一定可以构造出\(ans=3\)的合法方案。构造方式如下:
- 不妨设\(n\leq m\),则\(m\geq3\)。
- 两个矩阵为
+,一个矩阵为-。 - 将第一个矩阵的第一列和奇数行的第二列到第\(m-1\)列设为\(1\)。
- 将第二个矩阵的第\(m\)列和偶数行的第二列到第\(m-1\)列设为\(1\)。
- 将两个矩阵第二列到第\(m-1\)列在目标矩阵中的对应位置为\(1\)的位置设为\(1\)(此时一定满足四联通性质)。
- 将第三个矩阵的第二列到第\(m-1\)列设为\(1\),第一列和第\(m\)列在目标矩阵中的对应位置为\(0\)的位置设为\(1\)。
此时一定可以构造出合法的方案,\(ans=3\)。
槽点:这题\(n,m\leq500\)挺垃圾的,为什么不开\(n,m\leq5000\)(虽说得稍微改一下实现)。
放代码:代码里面有些重复的东西是复制出来的所以看起来可能会有点丑...
#include<bits/stdc++.h>
using namespace std;
const int N=502,fx[2][4]={{0,0,1,-1},{1,-1,0,0}};
int n,m;
char s[N][N],t[N][N],r[N][N],q[N][N];
int vis[N][N],cnt[2];
bool check0(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='1'){
return 0;
}
}
}
return 1;
}
void solve0(){
printf("0\n");
}
void dfs1(int u,int v){
if(vis[u][v]){
return;
}
vis[u][v]=1;
for(int i=0,tx,ty;i<4;i++){
tx=u+fx[0][i];ty=v+fx[1][i];
if(tx<1||ty<1||tx>n||ty>m){
continue;
}
if(s[tx][ty]=='1'&&!vis[tx][ty]){
dfs1(tx,ty);
}
}
}
bool check1(){
memset(vis,0,sizeof vis);
bool flag=1;
for(int i=1;i<=n;i++){
if(!flag){
break;
}
for(int j=1;j<=m;j++){
if(s[i][j]=='1'){
dfs1(i,j);
flag=0;
break;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='1'){
if(!vis[i][j]){
return 0;
}
}
}
}
return 1;
}
void solve1(){
printf("1\n+\n");
for(int i=1;i<=n;i++){
printf("%s\n",s[i]+1);
}
}
set<int>st;
void dfs2(int u,int v,int w){
if(vis[u][v]){
return;
}
vis[u][v]=w;
for(int i=0,tx,ty;i<4;i++){
tx=u+fx[0][i];ty=v+fx[1][i];
if(tx<1||ty<1||tx>n||ty>m){
continue;
}
if(s[tx][ty]=='0'&&!vis[tx][ty]){
dfs2(tx,ty,w);
}
else if(s[tx][ty]=='1'){
st.insert(vis[tx][ty]);
}
}
}
void dfs21(int u,int v,int w){
if(vis[u][v]){
return;
}
vis[u][v]=w;
for(int i=0,tx,ty;i<4;i++){
tx=u+fx[0][i];ty=v+fx[1][i];
if(tx<1||ty<1||tx>n||ty>m){
continue;
}
if(s[tx][ty]=='1'&&!vis[tx][ty]){
dfs21(tx,ty,w);
}
}
}
bool check2(){
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='1'&&!vis[i][j]){
dfs21(i,j,++cnt[1]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='0'&&!vis[i][j]){
st.clear();
dfs2(i,j,++cnt[0]);
if((int)st.size()==cnt[1]){
return 1;
}
}
}
}
return 0;
}
void solve2(){
printf("2\n");
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
t[i][j]=s[i][j];
q[i][j]='0';
if(s[i][j]=='0'&&vis[i][j]==cnt[0]){
t[i][j]='1';q[i][j]='1';
}
}
}
printf("+\n");
for(int i=1;i<=n;i++){
printf("%s\n",t[i]+1);
}
printf("-\n");
for(int i=1;i<=n;i++){
printf("%s\n",q[i]+1);
}
}
int lb[N],rb[N];
void solven1(){
memset(vis,0,sizeof vis);
memset(cnt,0,sizeof cnt);
memset(lb,0x3f,sizeof lb);
for(int i=1;i<=m;i++){
if(s[1][i]=='1'){
if(vis[1][i]){
continue;
}
dfs21(1,i,++cnt[1]);
}
}
for(int i=1;i<=m;i++){
if(vis[1][i]){
lb[vis[1][i]]=min(lb[vis[1][i]],i);
rb[vis[1][i]]=max(rb[vis[1][i]],i);
}
}
int ans=cnt[1],lmt,ll=1,rr=cnt[1];
printf("%d\n",ans);
if(cnt[1]&1){
lmt=ans>>1;
for(int i=1;i<=lmt;i++){
printf("+\n");
for(int j=1;j<=m;j++){
t[1][j]='0';
}
for(int j=lb[ll];j<=rb[rr];j++){
t[1][j]='1';
}
printf("%s\n",t[1]+1);
printf("-\n");
for(int j=1;j<=m;j++){
t[1][j]='0';
}
for(int j=rb[ll]+1;j<lb[rr];j++){
t[1][j]='1';
}
printf("%s\n",t[1]+1);
ll++;rr--;
}
for(int j=1;j<=m;j++){
t[1][j]='0';
}
for(int j=lb[ll];j<=rb[ll];j++){
t[1][j]='1';
}
printf("+\n");
printf("%s\n",t[1]+1);
}
else{
lmt=ans>>1;
for(int i=1;i<=lmt;i++){
printf("+\n");
for(int j=1;j<=m;j++){
t[1][j]='0';
}
for(int j=lb[ll];j<=rb[rr];j++){
t[1][j]='1';
}
printf("%s\n",t[1]+1);
printf("-\n");
for(int j=1;j<=m;j++){
t[1][j]='0';
}
for(int j=rb[ll]+1;j<lb[rr];j++){
t[1][j]='1';
}
printf("%s\n",t[1]+1);
ll++;rr--;
}
}
}
void solvem1(){
memset(vis,0,sizeof vis);
memset(cnt,0,sizeof cnt);
memset(lb,0x3f,sizeof lb);
for(int i=1;i<=n;i++){
if(s[i][1]=='1'){
if(vis[i][1]){
continue;
}
dfs21(i,1,++cnt[1]);
}
}
for(int i=1;i<=n;i++){
if(vis[i][1]){
lb[vis[i][1]]=min(lb[vis[i][1]],i);
rb[vis[i][1]]=max(rb[vis[i][1]],i);
}
}
int ans=cnt[1],lmt,ll=1,rr=cnt[1];
printf("%d\n",ans);
if(cnt[1]&1){
lmt=ans>>1;
for(int i=1;i<=lmt;i++){
printf("+\n");
for(int j=1;j<=n;j++){
t[j][1]='0';
}
for(int j=lb[ll];j<=rb[rr];j++){
t[j][1]='1';
}
for(int j=1;j<=n;j++){
printf("%s\n",t[j]+1);
}
printf("-\n");
for(int j=1;j<=n;j++){
t[j][1]='0';
}
for(int j=rb[ll]+1;j<lb[rr];j++){
t[j][1]='1';
}
for(int j=1;j<=n;j++){
printf("%s\n",t[j]+1);
}
ll++;rr--;
}
for(int j=1;j<=n;j++){
t[j][1]='0';
}
for(int j=lb[ll];j<=rb[ll];j++){
t[j][1]='1';
}
printf("+\n");
for(int j=1;j<=n;j++){
printf("%s\n",t[j]+1);
}
}
else{
lmt=ans>>1;
for(int i=1;i<=lmt;i++){
printf("+\n");
for(int j=1;j<=n;j++){
t[j][1]='0';
}
for(int j=lb[ll];j<=rb[rr];j++){
t[j][1]='1';
}
for(int j=1;j<=n;j++){
printf("%s\n",t[j]+1);
}
printf("-\n");
for(int j=1;j<=n;j++){
t[j][1]='0';
}
for(int j=rb[ll]+1;j<lb[rr];j++){
t[j][1]='1';
}
for(int j=1;j<=n;j++){
printf("%s\n",t[j]+1);
}
ll++;rr--;
}
}
}
void ssolve(){
printf("3\n");
for(int i=1;i<=m;i++){
t[1][i]='1';t[n][i]='0';
r[1][i]='0';r[n][i]='1';
for(int j=2;j<n;j++){
t[j][i]=s[j][i];r[j][i]=s[j][i];
}
if(i&1){
for(int j=1;j<n;j++){
t[j][i]='1';
}
}
else{
for(int j=2;j<=n;j++){
r[j][i]='1';
}
}
}
for(int i=1;i<=m;i++){
q[1][i]=(s[1][i]!='1'?'1':'0');
q[n][i]=(s[n][i]!='1'?'1':'0');
for(int j=2;j<n;j++){
q[j][i]='1';
}
}
printf("+\n");
for(int i=1;i<=n;i++){
printf("%s\n",t[i]+1);
}
printf("+\n");
for(int i=1;i<=n;i++){
printf("%s\n",r[i]+1);
}
printf("-\n");
for(int i=1;i<=n;i++){
printf("%s\n",q[i]+1);
}
}
void solve(){
printf("3\n");
for(int i=1;i<=n;i++){
t[i][1]='1';t[i][m]='0';
r[i][1]='0';r[i][m]='1';
for(int j=2;j<m;j++){
t[i][j]=s[i][j];r[i][j]=s[i][j];
}
if(i&1){
for(int j=1;j<m;j++){
t[i][j]='1';
}
}
else{
for(int j=2;j<=m;j++){
r[i][j]='1';
}
}
}
for(int i=1;i<=n;i++){
q[i][1]=(s[i][1]!='1'?'1':'0');
q[i][m]=(s[i][m]!='1'?'1':'0');
for(int j=2;j<m;j++){
q[i][j]='1';
}
}
printf("+\n");
for(int i=1;i<=n;i++){
printf("%s\n",t[i]+1);
}
printf("+\n");
for(int i=1;i<=n;i++){
printf("%s\n",r[i]+1);
}
printf("-\n");
for(int i=1;i<=n;i++){
printf("%s\n",q[i]+1);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
if(check0()){
solve0();return 0;
}
if(check1()){
solve1();return 0;
}
if(check2()){
solve2();return 0;
}
if(n==1){
solven1();return 0;
}
if(m==1){
solvem1();return 0;
}
if(m==2){
ssolve();
}
else{
solve();
}
return 0;
}
noi.ac NA529 【神树的矩阵】的更多相关文章
- noi.ac #529 神树的矩阵
题目链接:戳我 当 \(max(n, m) \ge 3\) 时,可以如下构造: 考虑下面这样三个矩阵,红 + 蓝 − 绿得到的矩阵是一个第一行和最后一行全是 1,其他地方全是 0 的矩阵. 那么如果需 ...
- noi.ac #531 神树和物品
题目链接:戳我 决策单调性 (蒟蒻终于会写决策单调性啦!考试全场切这题就我不会啊嘤) (证明?不会啊,自己打表看QAQ) 44pts \(O(n^2)\)代码: #include<iostrea ...
- noi.ac #528 神树和排列
题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorith ...
- noi.ac #525 神树的权值
mcfx神仙的题qwq 题目链接:戳我 首先,我们知道30%的分还是挺好做的 直接枚举根,然后dfs一遍以\(O(n)\)的时间复杂度求出来有多少神仙点 代码如下: #include<iostr ...
- NOI.AC NOIP模拟赛 第三场 补记
NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...
- # NOI.AC省选赛 第五场T1 子集,与&最大值
NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...
- NOI.ac #31 MST DP、哈希
题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...
- NOI.AC NOIP模拟赛 第五场 游记
NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...
- NOI.AC NOIP模拟赛 第六场 游记
NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...
随机推荐
- Debian系统软件安装
查看已安装软件 dpkg -l | grep -i name apt-get remove name 建议用root安装,有一些工具,使用非root用户安装后,仍然不识别命令,可能跟权限有关. net ...
- AttributeError: module 'html.parser' has no attribute 'HTMLParseError'
别人说这种错误大多是,因为beautifulsoup的版本兼容问题, 因为beautifulsoup的4.0以下版本和4.0版本与python3.5以上都不兼容, 网上的解决方案大多是:降python ...
- 【AMAD】betamax -- 一个ruby-VCR的模仿品,只支持requests
简介 动机 作用 用法 个人评分 简介 betamax1会记录你的HTTP操作,可以让你在测试的时候不必重复进行真实的请求. 动机 如果你的代码需要和外部资源一起运作,那么测试这段代码的方法就叫做集成 ...
- 【神经网络与深度学习】GLOG介绍
一.安装配置 1.简介 google 出的一个C++轻量级日志库,支持以下功能: ◆ 参数设置,以命令行参数的方式设置标志参数来控制日志记录行为: ◆ 严重性分级,根据日志严重性分级记录日志: ◆ 可 ...
- DataGridView中的ComboboxCell报了System.ArgumentException:DagaGridViewComboBoxCell值无效错误
原因是初始化的时候给ComboboxCell绑定了一系列的值,但是真正赋值的时候却给了一个不在那一系列值范围中的值,所以就报了这个错 在开发的时候难免会因为数据的问题出现这个问题,为了不让系统崩掉,就 ...
- MYSQL—第二部分(Linux版本的安装和数据表的操作)
Linux版本的安装(过于简单了) 安装: ? 1 yum install mysql-server 服务端启动 ? 1 mysql.server start 客户端连接 ? 1 2 3 4 5 6 ...
- python接口自动化-重定向(Location)
一.重定向 1.重定向(redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置,从地址A跳转到地址B了. 2.重定向状态码: --301 redirect: 301 代表永久性转移( ...
- mysql5.6 多实例标准化安装
1.检查防火墙 是否关闭service iptables stopchkconfig iptables offservice iptables status 2. SELINUXvim /etc/se ...
- SQL的循环嵌套算法:NLP算法和BNLP算法
MySQL的JOIN(二):JOIN原理 表连接算法 Nested Loop Join(NLJ)算法: 首先介绍一种基础算法:NLJ,嵌套循环算法.循环外层是驱动表,循坏内层是被驱动表.驱动表会驱动被 ...
- 设计模式:备忘录模式(Memento)
个人比较喜欢玩单机游戏,什么仙剑.古剑.鬼泣.使命召唤.三国无双等等一系列的游戏我都玩过(现在期待凡人修仙传),对于这些游戏除了剧情好.场面大.爽快之外,还可以随时存档,等到下次想玩了又可以从刚开始的 ...