poj1753 (高斯消元法求异或方程组)

题目链接:http://poj.org/problem?id=1753

题意:经典开关问题,和poj1222一样,进行两次高斯消元即可,只用初始化的时候改一下初始状态。可能存在无解或多解的情况,多解要枚举自由变元的所有状态。

AC代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;

const int maxn=20;
const int inf=0x3f3f3f3f;
int mp[5][5],a[maxn][maxn],x[maxn],equ,var,free_x[maxn];
char s[5];

void init(int p){
    memset(a,0,sizeof(a));
    for(int i=0;i<4;++i){
        for(int j=0;j<4;++j){
            int t=i*4+j;
            a[t][16]=p^mp[i][j];
            a[t][t]=1;
            if(i>0) a[t][(i-1)*4+j]=1;
            if(i<3) a[t][(i+1)*4+j]=1;
            if(j>0) a[t][i*4+j-1]=1;
            if(j<3) a[t][i*4+j+1]=1;
        }
    }
}

int Gauss(){
    int r=0,cnt=0;
    for(int c=0;r<equ&&c<var;++r,++c){
        int Maxr=r;
        for(int i=r+1;i<equ;++i){
            if(abs(a[i][c])>abs(a[Maxr][c]))
                Maxr=i;
        }
        if(Maxr!=r){
            for(int i=c;i<var+1;++i)
                swap(a[r][i],a[Maxr][i]);
        }
        if(!a[r][c]){
            --r;
            free_x[cnt++]=c;
            continue;
        }
        for(int i=r+1;i<equ;++i){
            if(!a[i][c]) continue;
            for(int j=c;j<var+1;++j)
                a[i][j]^=a[r][j];
        }
    }
    for(int i=r;i<equ;++i)
        if(a[i][var])
            return -1;
    return var-r;
}

int solve(int t){
    int ret=inf;
    for(int i=0;i<(1<<t);++i){
        int cnt=0;
        memset(x,0,sizeof(x));
        for(int j=0;j<t;++j){
            if((i>>j)&1){
                ++cnt;
                x[free_x[j]]=1;
            }
        }
        for(int j=var-t-1;j>=0;--j){
            int tmp=a[j][var],tp,ok=1;
            for(int k=j;k<var;++k){
                if(!a[j][k]) continue;
                if(ok){
                    ok=0;
                    tp=k;
                }
                else{
                    tmp^=x[k];
                }
            }
            x[tp]=tmp;
            cnt+=x[tp];
        }
        ret=min(ret,cnt);
    }
    return ret;
}

int main(){
    equ=var=16;
    for(int i=0;i<4;++i){
        scanf("%s",s);
        for(int j=0;j<4;++j)
            if(s[j]==‘b‘) mp[i][j]=0;
            else mp[i][j]=1;
    }
    init(0);
    int t1,t2,t3,t4;
    t1=Gauss();
    if(t1!=-1) t2=solve(t1);
    init(1);
    t3=Gauss();
    if(t3!=-1) t4=solve(t3);
    if(t1==-1&&t3==-1)
        printf("Impossible\n");
    else
        printf("%d\n",min(t2,t4));
    return 0;
}

原文地址:https://www.cnblogs.com/FrankChen831X/p/11772530.html

时间: 2024-10-14 20:49:49

poj1753 (高斯消元法求异或方程组)的相关文章

(模板)poj1681 高斯消元法求异或方程组(无解、唯一解、多解)

题目链接:https://vjudge.net/problem/POJ-1681 题意:类似于poj1222,有n×n的01矩阵,翻转一个点会翻转其上下左右包括自己的点,求最少翻转多少点能使得矩阵全0. 思路: 同样的可以枚举第一行的状态,这里不说了. 用高斯消元法来解这道题,每个点的状态表示一个变量,那么有n*n个方程,n*n个变量的方程组,用高斯消元法来解,可能存在无解,唯一解,多解的情况.多解的时候要枚举自由变元的状态. AC代码: /* poj1681 开关问题,高斯消元法解异或方程组

POJ 1222 (开关问题+高斯消元法)

题目链接: http://poj.org/problem?id=1222 题目大意:一堆开关,或开或关.每个开关按下后,周围4个方向开关反转.问使最后所有开关都关闭的,开关按法.0表示不按,1表示按. 解题思路: 一共只有5*6个开关. 对于每个开关,设其最终状态为x5,上下左右四个开关最终状态分别为x1,x2,x3,x4, 那么有方程x1^x2^x3^x4^x5^初始状态=0. 这样就有30个方程.解这30个线性方程组即可. 用高斯消元法来解方程组,变化如下: ①对于原本找列中绝对值最大这一步

小游戏 Lights Out (关灯) 的求解 —— 异或方程组

Author : Evensgn  Blog Link : http://www.cnblogs.com/JoeFan/ Article Link : http://www.cnblogs.com/JoeFan/p/4338003.html   游戏介绍 Lights Out (关灯)是一款据说在20世纪90年代就已经被设计出的小游戏,游戏的玩法十分简单. 首先,给定一个 n 行 m 列的矩形方格阵,每个格子上都有一盏灯. 初始时,有些灯是开着的,有些灯是关着的. 玩家每次进行一次操作,选中一盏

[POJ 1222] EXTENDED LIGHTS OUT

题目 http://acm.pku.edu.cn/JudgeOnline/problem?id=1222 描述 给你一个5行6列的矩阵分别表示30个灯,矩阵map[i][j]为1表示灯亮着, 0表示灯没亮. 要求你输出解决方案. press[i][j]为1表示按一下,0表示不按.使得最后状态为所有灯都熄灭. 分析 高斯消元法(Gaussian elimination method) => 对于每个格子 map[i][j], 能影响他的格子为 (i-1, j), (i, j-1), (i+1, j

BestCoder Round #90

有生以来第一场在COGS以外的地方打的比赛.挂成dog了. 主要是没有经验,加之代码能力过弱.还有最后的瞎hack三次,Too Young Too Simple...... 言归正传. (抄一发题解先) T1 Kblack loves flag 用两个布尔数组分别维护每个行/列是否被插过旗帜,最后枚举每一行.列统计答案即可.空间复杂度O(n+m),时间复杂度O(n+m+k). T2 dingyeye loves stone 设根节点的深度为0,将所有深度为奇数的节点的石子数目xor起来,则先手必

2016 CCPC 网络赛 B 高斯消元 C 树形dp(待补) G 状压dp+容斥(待补) H 计算几何

2016 CCPC 网络赛 A - A water problem 水题,但读题有个坑,输入数字长度很大.. B - Zhu and 772002 题意:给出n个数(给出的每个数的质因子最大不超过2000),选出多个数相乘得b.问有多少种选法让b 为完全平方数. tags:高斯消元,求异或方程组解的个数.   好题 每个数先素数分解开.  对于2000以内的每个素数p[i],这n个数有奇数个p[i]则系数为1,偶数个则系数为0,最后n个数的p[i]系数异或和都要为0才会使得最后的积为完全平方数.

用最小二乘法进行多项式拟合

利用最小二乘法进行多项式拟合时,最终归结为求解一个关于a1, a2, a3, ..., an的线性方程组,其矩阵表示如下: 求解该方程组的方法有两种. 其一,用高斯消元法,解方程组. 其二,用矩阵运算,X*A=Y,则A=X^-1*Y.

SDOI2010选做

\(Round1~D1T1\)外星千足虫 \(BSOJ2793\)--高斯消元解异或方程组 简述 有\(n\)个数\(\{a_i\}\) 给出\(m\)个信息,每个信息给出\(\displaystyle{(\sum_{i=1}^m a_{b_i})\bmod 2}\)(\(\{b_i\}\)是\({1,2,\cdots,n}\)的子集) 求最少几次操作即可确定可能取值 Solution \(70pts'\) 给出的信息可以转化为\(\displaystyle{\oplus_{i=1}^m a_{

fzu1704(高斯消元法解异或方程组+高精度输出)

题目链接:https://vjudge.net/problem/FZU-1704 题意:经典开关问题,求使得灯全0的方案数. 思路:题目保证至少存在一种方案,即方程组一定有解,那么套上高斯消元法的板子,求出自由变元的个数t,方案总数即2t,t可能大于64,要用到高精度计算. AC代码: #include<iostream> #include<string> #include<cstdio> #include<cstdlib> #include<algo