poj1830 高斯消元法

这篇博客介绍了如何利用高斯消元法解决POJ1830中的二进制线性方程组问题。通过逐行消元和矩阵求秩,判断解的个数,当增广矩阵与系数矩阵秩不等时,表示无解,否则解的个数是2的(n-秩)次方。文章中还提到了在解决过程中需要注意的细节和可能遇到的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
 * poj1830 高斯消元法(线性代数,矩阵求秩) 
 * 就是一个解二进制的线性方程组,求解的个数,如果增广阵和系数阵的秩不等,那就无解,否则解的个数是2^(n-秩)
 * 求秩的过程就是逐行消去的过程,最左列为1的行下面,该列都消去为0,最后统计非全0的行就是秩了
 * 这个题一上来先把xy搞混了,结果WA了好多次都没搞清楚错在哪儿 后来索性试了一下,才解决了问题
 */
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int MAX_NUM = 30;

bool sw[MAX_NUM][MAX_NUM];
bool start[MAX_NUM],end[MAX_NUM],target[MAX_NUM];

void swap(bool& a,bool& b){
    bool tmp = a;
    a=b;
    b=tmp;
}

int main(){
    int k,n,tmp,x,y;
    scanf("%d",&k);
    while(k--){
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                sw[i][j] = (i==j);
            }
        }

        for(int i=0;i<n;++i){
            scanf("%d",&tmp);
            start[i] = (tmp == 1);
        }

        for(int i=0;i<n;++i){
            scanf("%d",&tmp);
            end[i] = (tmp == 1);
            target[i] = start[i] ^ end[i];
        }

        //scanf("%d%d",&x,&y);
        scanf("%d%d",&y,&x);
        while(x!=0 && y!=0){
            sw[x-1][y-1] = true;
            //scanf("%d%d",&x,&y);
            scanf("%d%d",&y,&x);
        }
        int op_row,op_col,rp,cp;
        //逐行,找到最高位的true,与当前最上面的行互换,将下面该位为true的行与该行做异或
        for(op_row=0,op_col=0;op_row<n,op_col<n;++op_row,++op_col){//op_col表示当前最高列
            int maxRow = op_row;
            //查找col列为true的行
            for(rp = op_row; rp < n; rp++){
                if(sw[rp][op_col]){
                    maxRow = rp;  
                    break;
                } 
            }

            if(maxRow != op_row){
                for(cp = op_col; cp < n; cp++){
                    swap(sw[op_row][cp], sw[maxRow][cp]);                    
                }
                swap(target[op_row],target[maxRow]);
            }
      
            if(rp >= n)   
            {  
                op_row--;  
                continue;  
            }  
            for(rp = op_row + 1; rp < n; rp++)  
            {  
                if(!sw[rp][op_col]) continue;  
                for(cp = op_col; cp < n; cp++){
                    sw[rp][cp] ^= sw[op_row][cp];
                }
                target[rp] ^= target[op_row];   
            }  

        }

        bool flag = true;
        //检查是否有解
        for(int i=n-1;i>=op_row;--i){
            if(target[i]){
                flag = false;
                printf("Oh,it's impossible~!!\n");
                break;
            }
        }

        if(flag){
            printf("%d\n", 1<<(n-op_row) );
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值