题目链接:戳我

当 \(max(n, m) \ge 3\) 时,可以如下构造:

考虑下面这样三个矩阵,红 + 蓝 − 绿得到的矩阵是一个第一行和最后一行全是 1,其他地方全是 0 的矩阵。

那么如果需要把中间某个位置变成 1,可以在红或蓝矩阵中的对应位置加一个 1。

如果需要把第一行或最后一行某个位置变成 0,可以在绿矩阵中的对应位置加一个 1。





然后对于其他情况分别特判就行了(具体哪些可以看main函数)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define MAXN 510
#define mp make_pair
using namespace std;
int n,m;
int move_x[4]={0,0,1,-1},move_y[4]={1,-1,0,0};
char s[MAXN][MAXN];
namespace subtask_0
{
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1')
return false;
return true;
}
}
namespace subtask_1
{
int done[MAXN][MAXN];
inline bool bfs(int x,int y)//不带done的清空操作
{
queue<pair<int,int> >q;
q.push(mp(x,y));
while(!q.empty())
{
int u_x=q.front().first;
int u_y=q.front().second;
q.pop();
done[u_x][u_y]=1;
for(int k=0;k<=3;k++)
{
int xx=u_x+move_x[k];
int yy=u_y+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0'||done[xx][yy]) continue;
done[xx][yy]=1;
q.push(mp(xx,yy));
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1'&&done[i][j]==0) return false;
return true;
}
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='1')
{
if(bfs(i,j)==true) return true;
else return false;
}
}
inline void solve()
{
printf("1\n+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",s[i][j]);
puts("");
}
}
}
namespace subtask_2
{
int cnt,cur_ans,pos;
int fa[MAXN*MAXN],id[MAXN][MAXN];
map<int,int>ex;
set<int>sset[MAXN*MAXN];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool check()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
id[i][j]=++cnt,fa[cnt]=cnt;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<=3;k++)
{
int xx=i+move_x[k];
int yy=j+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[i][j]!=s[xx][yy]) continue;
int t=find(id[i][j]),tt=find(id[xx][yy]);
if(t!=tt) fa[t]=tt;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0') continue;
int t=find(id[i][j]);
if(!ex.count(t)) ex[t]=1,cur_ans++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0')
for(int k=0;k<=3;k++)
{
int xx=i+move_x[k];
int yy=j+move_y[k];
if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0') continue;
int t=find(id[i][j]),tt=find(id[xx][yy]);
sset[t].insert(tt);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(s[i][j]=='0')
{
int t=find(id[i][j]);
if((int)sset[t].size()==cur_ans)
{
pos=t;
break;
}
}
if(pos!=0) break;
}
if(pos==0) return false;
return true;
}
inline void solve()
{
printf("2\n+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='1'||(s[i][j]=='0'&&find(id[i][j])==pos)) printf("1");
else printf("0");
}
puts("");
}
printf("-\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='0'&&find(id[i][j])==pos) printf("1");
else printf("0");
}
puts("");
}
}
}
inline void solve_n_1()
{
vector<pair<int,int> >vec;
int now=1;
while(now<=m)
{
int cnt1,cnt2;
while(now<=m&&s[1][now]=='0') now++;
if(now<=m&&s[1][now]=='1')
{
cnt1=now;
while(now<=m&&s[1][now]=='1') now++;
cnt2=now-1;
vec.push_back(mp(cnt1,cnt2));
}
}
printf("%d\n",(int)vec.size());
for(int i=0;i<vec.size();i++)
{
printf("+\n");
for(int j=1;j<=m;j++)
{
if(vec[i].first<=j&&j<=vec[i].second) printf("1");
else printf("0");
}
puts("");
}
}
inline void solve_m_1()
{
vector<pair<int,int> >vec;
int now=1;
while(now<=n)
{
int cnt1,cnt2;
while(now<=n&&s[now][1]=='0') now++;
if(now<=n&&s[now][1]=='1')
{
cnt1=now;
while(now<=n&&s[now][1]=='1') now++;
cnt2=now-1;
vec.push_back(mp(cnt1,cnt2));
// printf("[%d %d]\n",cnt1,cnt2);
}
}
printf("%d\n",(int)vec.size());
for(int i=0;i<vec.size();i++)
{
printf("+\n");
for(int j=1;j<=n;j++)
{
if(vec[i].first<=j&&j<=vec[i].second) printf("1\n");
else printf("0\n");
}
// puts("");
}
}
namespace others
{
char t[MAXN][MAXN],r[MAXN][MAXN],q[MAXN][MAXN];
inline void print()
{
printf("3\n");
printf("+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",t[i][j]);
puts("");
}
printf("+\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",r[i][j]);
puts("");
}
printf("-\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",q[i][j]);
puts("");
}
}
inline void solve_m_2()
{
for(int i=1;i<=n;i++)
{
t[i][1]='1';
t[i][2]=(s[i][2]=='1'?'1':'0');
}
for(int i=1;i<=n;i++)
{
r[i][2]='1';
r[i][1]=(s[i][1]=='1'?'1':'0');
}
for(int i=1;i<=n;i++) q[i][1]=q[i][2]='1';
print();
}
inline void solve()
{
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]=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]=='0'?'1':'0');
q[i][m]=(s[i][m]=='0'?'1':'0');
for(int j=2;j<m;j++) q[i][j]='1';
}
print();
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
// freopen("ce.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
if(subtask_0::check()) printf("0\n");
else if(subtask_1::check()) subtask_1::solve();
else if(subtask_2::check()) subtask_2::solve();
else if(n==1) solve_n_1();
else if(m==1) solve_m_1();
else if(m==2) others::solve_m_2();
else others::solve();
return 0;
}

noi.ac #529 神树的矩阵的更多相关文章

  1. noi.ac #531 神树和物品

    题目链接:戳我 决策单调性 (蒟蒻终于会写决策单调性啦!考试全场切这题就我不会啊嘤) (证明?不会啊,自己打表看QAQ) 44pts \(O(n^2)\)代码: #include<iostrea ...

  2. noi.ac #528 神树和排列

    题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorith ...

  3. noi.ac #525 神树的权值

    mcfx神仙的题qwq 题目链接:戳我 首先,我们知道30%的分还是挺好做的 直接枚举根,然后dfs一遍以\(O(n)\)的时间复杂度求出来有多少神仙点 代码如下: #include<iostr ...

  4. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  5. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

  6. NOI.ac #31 MST DP、哈希

    题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...

  7. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  8. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  9. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

随机推荐

  1. DL4J中文文档/Keras模型导入/函数模型

    导入Keras函数模型 假设使用Keras的函数API开始定义一个简单的MLP: from keras.models import Model from keras.layers import Den ...

  2. css多种方式实现等宽布局

    本文讲的等宽布局是在不手动设置元素宽度的情况下,使用纯css实现各个元素宽度都相当的效果. 1.使用table-cell实现(兼容ie8) <style> body,div{ margin ...

  3. vue配置外放generate-asset-webpack-plugin

    解决方法:(共有2个方法) 1.借助插件  generate-asset-webpack-plugin .在webpack.prod.conf.js中去生成configServer.json文件,让其 ...

  4. git的详细安装

    git的详细安装 Git 是时候动手尝试下 Git 了,不过得先安装好它.有许多种安装方式,主要分为两种,一种是通过编译源代码来安装:另一种是使用为特定平台预编译好的安装包. 从源代码安装 若是条件允 ...

  5. 佳能单反SDK 步骤

    EdsInitializeSDK(); EdsGetCameraList(&eclr);//获取相机列表 EdsGetChildCount(eclr, &camCount);  //获 ...

  6. vim insert VISUAL模式无法右键复制问题(转)

    转自:https://blog.csdn.net/coder_oyang/article/details/89096219 vim中使用鼠标右键粘贴,失败.vim的模式: 网上解法: 1. 普通模式下 ...

  7. mysql一些语句

    <!-- 报警量排行按创建时间每月来排行 --> <select id="alarmDaySort" resultType="alarm"&g ...

  8. 怎么处理U盘无法正常弹出的情况?

    我们都知道U盘和移动硬盘在使用完毕后需要点击“安全删除硬件并弹出”后才能拔出,这样可以避免U盘还在工作时被拔出而造成的故障. 但有时我们点击“安全删除硬件并弹出”时,系统会提示U盘正在工作,没有办法停 ...

  9. Centos 7.0 界面

    执行:systemctl get-default //显示默认的界面方式 multi-user.target //命令行界面 graphical.target //图形化界面 执行:systemctl ...

  10. Java面向对象(一)

    面向对象(Object Oriented) 面向过程:事物比较简单.将问题分解为若干个步骤.按照步骤依次执行.面向对象:事物比较复杂.在解决面向对象的过程中,最后的执行部分还是面向过程方式,面向过程和 ...