[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 }
View Code

【总结】

构造很奇妙,需要脑回路清奇

 

posted @ 2017-10-27 20:59  Danzel♂  阅读(383)  评论(1编辑  收藏  举报