【CQOI2014】和谐矩阵

【CQOI2014】和谐矩阵

Time Limits: 1s Memory Limits: 512MB Special Judge

Description
我们称一个由0和1组成的矩阵是和谐的,当且仅当每个元素都有偶数个相邻的1.一个元素相邻的元素包括它本身,及他上下左右的4个元素(如果存在)。
给定矩阵的行数和列数,请计算并输出一个和谐的矩阵。注意:所有元素为0的矩阵是不允许的。

Input
输入一行,包含两个空格分隔的整数m和n,分别表示矩阵的行数和列数。

Output
输出包含m行,每行n个空格分隔整数(0或1),为所求矩阵。测试数据保证有解。

Sample Input

4 4

Sample Output

0 1 0 0
1 1 1 0
0 0 0 1
1 1 0 1

Data Constraint
1<=m,n<=40


题目大意:

求一个非全0的n*m的01矩阵,使得每个位置满足:与其相邻或本身的’1’的个数为偶数


解题思路

emm。。。难道是构造?好吧感觉不太可能。

算法1

先说说一个很朴素的思路:
发现了这个没?——

0 1 0 0 0 1 0 0 0 1 0
1 1 1 0 1 1 1 0 1 1 1
0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 1 1 1 0 1 1 1
0 1 0 0 0 1 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 0 0 0 1 0
1 1 1 0 1 1 1 0 1 1 1

这个方阵是成立的,找找规律——方阵由小方阵组成,方阵中间有0间隔,且相邻的方阵对称。上矩阵中,小方阵为:

0 1 0
1 1 1

观察一下,发现小方阵的内部也是成立的
同时,由于相邻的方阵对称,方阵之间的0只有左右或上下2个1,中间的依然成立
故整个方阵成立

于是——是否可以枚举使用多小的方阵,通过翻转求大方阵呢?
反正我没这么实践。

算法2

我想,假设一开始全都为0
每个点及周围的奇偶性(简单写了,意义如题)为0(偶,1为奇),假设选择某个点,只能影响到自身及周围的奇偶性,恰好是取反。
对于一个符合要求的矩阵,每个点的奇偶性为0,也就是说,对于每个点所带来的影响,等同于这个矩阵选其他点带来的影响。
for example
一个符合要求的矩阵:1 1 0 1 11 1 0 1 00 0 0 0 1组成;
1 1 0 1 0的影响为0 0 0 1 10 0 0 0 1的影响为0 0 0 1 1等同于1 1 0 1 0的影响;
根据这个思路,我们设 f(i,j) 表示选(i,j)带来的影响,那么一个满足要求的图选的点集为D,有 Xor(i,j)Df(i,j)= ,同时 f(i,j)=Xor(x,y)D,(x,y)(i,j)f(x,y) ,这个利用线性基可以实现。每次塞入 f(i,j) ,返回的是能否由线性基的某些状态构成,记录下能由哪些状态构成即可,bitset维护。
虽然理论上是 O((nm)3ω) 但线性基不可能每一位都异或,实际上nm=5000也能过

#include<cstring>
#include<cstdio>
#include<bitset>
#define N 22501
#define bt bitset<N>
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define f(a,b) ((a-1)*m+b-1)

using namespace std;

int n,m,T;

struct B{
    bt sta,mem;
    void clear(){
        sta.reset();mem.reset();
    }
}tmp;
struct Base{
    B l[N];
    B ins(B a){
        fd(i,T,0)if(a.sta[i]){
            if(l[i].sta.none()){
                l[i]=a;break;
            }a.sta^=l[i].sta;a.mem^=l[i].mem;
        }return a;
    }
    void init(){
        fd(i,T,0)l[i].clear();
    }
}graph;

int main(){
    scanf("%d %d",&n,&m);T=n*m-1;graph.init();
    fo(i,1,n)fo(j,1,m){
        tmp.clear();
        tmp.mem.set(f(i,j));
        tmp.sta.set(f(i,j));
        if(i>1)tmp.sta.set(f(i-1,j));
        if(j>1)tmp.sta.set(f(i,j-1));
        if(i<n)tmp.sta.set(f(i+1,j));
        if(j<m)tmp.sta.set(f(i,j+1));
        tmp=graph.ins(tmp);
        if(tmp.sta.none()){
            fo(I,1,n){
                fo(J,1,m)if(tmp.mem[f(I,J)])printf("1 ");else printf("0 ");printf("\n");
            }
            fclose(stdin);fclose(stdout);
            return 0;
        }
    }printf("-1");
}

猜你喜欢

转载自blog.csdn.net/white_elephant/article/details/79006626
今日推荐