题目链接:戳我

当 \(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. T100——取得系统参数值,如关帐日期

    CALL cl_get_para(g_enterprise,g_site,'S-MFG-0031') RETURNING l_para_data 用此方法获取关帐日期

  2. 怎样在 Vue 里面使用自定义事件将子组件的数据传回给父组件?

    首先, Vue 里面的组件之间的数据流动是 单向 的, 数据可以从父组件传递给子组件, 但不能从子组件传递给父组件, 因为组件和组件之间是 隔离 的. 就像两个嵌套的 黑盒子 . 能通过 props ...

  3. C#int类型 转Byte[]

    方法1:使用左移和右移 int转化为byte[]:   public  byte[] intToBytes(int value)         {             byte[] src = ...

  4. Ioc和Aop底层原理

    Spring中主要用到的设计模式有工厂模式和代理模式. IOC:Inversion of Control控制反转,也叫依赖注入,通过 sessionfactory 去注入实例:IOC就是一个生产和管理 ...

  5. MYSQL 修改语句(数据)

    修改数据(UPDATE)     如果你失忆了,希望你能想起曾经为了追求梦想的你.     我们玩QQ.微信.淘宝等等,都会有一个操作:修改信息   淘宝常用的嘛,新增了收货地址,也可以修改它,微信/ ...

  6. 安装grafna已经grafna对接zabbix

    安装插件 grafana-cli plugins install alexanderzobnin-zabbix-app 重启grafna systemctl restart grafana-serve ...

  7. 解决GitHub下载资源慢的问题

    打开 C:\Windows\System32\drivers\etc\hosts 添加 # GitHub 解决下载速度慢的问题 192.30.253.113 github.com 151.101.18 ...

  8. vim 去掉自动注释和自动回车

    取消 :set paste 恢复 :set paste!

  9. 关于SAMBA的关键参考资源

    https://www.samba.org/samba/docs/man/ https://devel.samba.org/ http://www.ubiqx.org/cifs/ https://ww ...

  10. 4、nfs(存储服务器)

    1.NFS基本概述 NFS是Network File System的缩写及网络文件系统.NFS的主要功能是通过局域网络让不同的主机系统之间可以共享文件或目录. 通常中小企业首选NFS作为集群架构的存储 ...