hdu 6952 / 2021“MINIEYE杯”中国大学生算法设计超级联赛(1) 1003 Puzzle loop (高斯消元解异或方程组)

https://acm.hdu.edu.cn/showproblem.php?pid=6952

 

题意:

n条横线m条竖线构成(n-1)*(m-1)的网格图,现在要求在图上沿线画若干个不相交圈,圈与圈之间可以共享点但不能共享线。

某些格子上有一个数0或者1,1表示这个格子周围4条线有奇数条属于画的圈,0表示偶数条。

 

难点在于如何转化画圈问题

画不相交的圈转化为n*m个交点周围4条线有偶数条属于画的圈

把格子的每条短线看作1个变量

结合0和1的要求构建异或方程组

 

#include<bits/stdc++.h>

using namespace std;

#define N 21

bitset<N*N*2>b[N*N*2];

int n,m;

int idh[N][N],idl[N][N];

char s[N][N];

const int mod=998244353;

long long gauss()
{
    int j,row=0;
    for(int i=0;i<m;++i)
    {
        j=row;
        while(j<n && !b[j][i]) ++j;
        if(j==n) continue;
        swap(b[row],b[j]);
        for(int k=row+1;k<n;++k)
            if(b[k][i]) b[k]^=b[row];
        ++row;
    }
    for(int i=row;i<n;++i) 
        if(b[i].test(m)) return 0; 
    int ans=1;
    for(int i=1;i<=m-row;++i) ans=1ll*ans*2%mod;
    return ans;
}

int main()
{
//    freopen("1.txt","w",stdout);
    int T,a,e;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&e);
        m=0;
        for(int i=1;i<=a;++i)
            for(int j=1;j<e;++j)
                idh[i][j]=m++;
        for(int i=1;i<=e;++i)
            for(int j=1;j<a;++j)
                idl[i][j]=m++;
        n=0;
        for(int i=1;i<=a;++i)
            for(int j=1;j<=e;++j)
            {
                if(j>1) b[n].set(idh[i][j-1]);
                if(j<e) b[n].set(idh[i][j]);
                if(i>1) b[n].set(idl[j][i-1]);
                if(i<a) b[n].set(idl[j][i]);
                ++n;
            //    printf("%d %d %d %d\n",idh[i][j-1],idh[i][j],idl[j][i-1],idl[j][i]);
            }
        for(int i=1;i<a;++i) scanf("%s",s[i]+1);
        for(int i=1;i<a;++i)
            for(int j=1;j<e;++j)
                if(s[i][j]!='.')
                {
                    b[n].set(idh[i][j]);
                    b[n].set(idh[i+1][j]);
                    b[n].set(idl[j][i]);
                    b[n].set(idl[j+1][i]);
            //        printf("%d %d %d %d\n",idh[i][j],idh[i+1][j],idl[j][i],idl[j+1][i]);            
                    if(s[i][j]=='1') b[n].set(m);
                    ++n;
                }
        printf("%d\n",gauss());
        for(int i=0;i<n;++i) b[i].reset();
    }
}

 

posted @ 2021-07-31 20:57  TRTTG  阅读(156)  评论(0编辑  收藏  举报