[noip模拟]B<构造>
【题目描述】
在两个n*m的网格上染色,每个网格中被染色的格子必须是一个四联通块(没有任何格子被染色也可以),四联通块是指所有染了色的格子可以通过网格的边联通,现在给出哪些格子在两个网格上都被染色了,保证网格的最外围一层不会在两个网格中同时被染色,即所有处于第x行第y列满足x=1或x=n或y=1或y=m的格子不会被在两个网格中同时被染色,请求出任意一种染色的方案,如果无解,请输出-1。
【输入格式】
第一行两个整数n,m
接下来一个n*m的01矩阵,共n行,每行m个数字,每个数字之间无空格,0表示没有同时被染色,1表示在两个网格中同时被染色。
【输出格式】
如果有解,则输出两个n*m的01矩阵,分别表示两个矩阵的染色情况,数字之间无空格,两个矩阵之间有一行空行
如果无解输出一行一个-1
【样例输入】
5 5
00000
01010
00000
01010
00000
【样例输出】
00000
01110
00010
01110
00000
01110
01010
01000
01010
01110
【样例解释】
第一个网格的染色 第二个网格的染色 紫色为在两个网格都染色的部分
(蓝色部分为四联通块) (红色部分为四联通块)
【数据范围】
对于20%的数据,n*m<=12
对于另外30%的数据,保证在两个矩阵都被染色的位置也是一个四联通块
对于100%的数据,n,m<=500
【思路】
这个题的题意有点皮,要多读几次才理解(当然大佬都是一看就懂QAQ)
20%的数据之间暴力就行,另外30%的数据其实直接输出你输入的矩阵两次就行
100%的数据的做法是玄学,大佬们管着叫构造(原谅我学识短不知道QAQ,我还以为是反向的模拟)
正解:
直接构造答案两个图的模版,构造的要求是两个图模板互不重合,但是能和除开边界的所有的格子相邻(因为重合点是不会出现在边界)
然后就可以开始愉快的构造了
这个构造首先是边界一圈两个图各分一半,然后内部二分给两家,保证一个图和另一个图除开边界的点相邻
然后无论重合点在哪都可以满足
构造的方式很多种,我举一个我自己的例子
橙色为答案图1,紫色为答案图2
然后你可以随意在非边界格子里选几个作为重合格子,只需要在这两张图中将重复格子赋值为1输出就行
答案初始图(以图片为例子)
11111 0 000001
101010 010101
101010 010101
101010 010101
101010 010101
100000 111110
然后假如我们输入的是
000000
010010
000000
010010
000000
000000
所以只需要在对应的初始图的点上赋值为1,然后输出图就行
输出:
11111 0 000001
111010 010111
101010 010101
111010 010111
101010 010101
100000 111110
我把重合点用红色写
1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #include<cmath>
5 #include<queue>
6 #include<algorithm>
7 #include<cstdlib>
8 #define maxn 505
9 using namespace std;
10
11 int n,m;
12 int ans1[maxn][maxn];
13 int ans2[maxn][maxn];
14
15 int read(){
16 int x=0,f=1;char ch=getchar();
17 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
18 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
19 return x*f;
20 }
21
22 void init(){
23 n=read();m=read();
24 for(int i=1;i<=n;i++)
25 for(int j=1;j<=m;j++)ans1[i][j]=1;
26 for(int i=1;i<=n;i++)ans1[i][m]=0,ans2[i][m]=1;
27 for(int i=2;i<=n;i++)
28 for(int j=2;j<=m;j+=2)
29 ans1[i][j]=0,ans2[i][j]=1;
30 for(int i=2;i<=m;i++)ans1[n][i]=0,ans2[n][i]=1;
31 }
32
33 void show(){
34 for(int i=1;i<=n;i++){
35 for(int j=1;j<=m;j++){
36 printf("%d",ans1[i][j]);
37 }printf("\n");
38 }
39 printf("\n");
40 for(int i=1;i<=n;i++){
41 for(int j=1;j<=m;j++){
42 printf("%d",ans2[i][j]);
43 }printf("\n");
44 }
45 }
46
47 void input(){
48 char ch=getchar();
49 for(int i=1;i<=n;i++){
50 int j=1;
51 while(ch<'0'||ch>'1'){ch=getchar();}
52 while(ch>='0'&&ch<='1'){
53 if(ch=='1')
54 ans1[i][j]=1,ans2[i][j]=1;
55 ch=getchar();j++;}
56 }
57 }
58
59 int main(){
60 init();
61 input();
62 show();
63 }
【总结】
构造很奇妙,需要脑回路清奇