poj1830 高斯消元开关问题

本文介绍了一种解决开关状态转换问题的算法,通过构建特定的矩阵并利用线性代数知识来确定从初始状态到目标状态的转换方法。讨论了如何根据开关间的依赖关系构建矩阵,并分析了解的可能数量。

  题目大意:
  给你一些开关的初始状态及终末状态,以及开关之间的关联关系;
  要求从初始状态变到终末状态的方法种数;

 思路:

  如对于开关i,j:代表改变开关i的状态,j的状态也会改变;
  由于j的状态是因为i的变化而变化,所以,对于我构造的矩阵a[i][j]
  i为行代表方程的编号,即此方程结果对应的开关编号,j代表未知数的系数;开关j随着开关i 变化,那么这里的i和j要相互交换位置!!!!因为行代表的是对应编号开关的状态;
  (至于我的前一篇开关问题里面为什么没有交换编号,那是因为他们之间是可以相互影响的)
  而这里的影响是单向的;
  再就是关于解的个数问题:
  联系线性代数的知识:r[A]代表系数矩阵的秩,r[A b]代表增广矩阵的秩;
  1,若二者相等则方程组有唯一解;
  2,若r[A b]大于r[A],则无解;
  3,若r[A b]小于r[A],则有无数组解(由于此题开关未知数只有1和0两种取值,所以其解的个数为2^(自由变元的个数);

至于方程等号右边应该取什么值,那就是此编号代表的开关的状态是否改变,若改变则为1,未改变则为0;

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=30;
int a[maxn+9][maxn+9],n,b[maxn+9];
int Gauss()
{
    int i,j,k,l;
    for(i=0,j=0; i<n&&j<n; i++,j++)
    {
        k=i;
        for(l=i+1; l<n; l++)
            if(a[l][j]>a[k][j]) k=l;
        if(k!=i)
        for(l=j; l<=n; l++)
            swap(a[k][l],a[i][l]);
        if(a[i][j]==0)//若寻找到的方程对应未知数的系数为零,那么就考虑此方程的下一个未知数系数,继续停留在此行,而不是接着下一行
        {
            i--;
            continue;
        }

        for(l=i+1; l<n; l++)
            if(a[l][j])//对应系数不为零才需要将其置为零
                for(int p=j; p<=n; p++)
                    a[l][p]^=a[i][p];//由于结果需要对二取模,其实就是抑或运算
    }
    for(l=i; l<n; l++)//此时代表此方程的系数矩阵全部为零,而等号右边并不为零,那么就是增广矩阵的秩大于系数矩阵,即为无解
        if(a[l][n]) return -1;
    if(i==n) return 1;//二者相等即有唯一解
    else return pow(2.0,n-i);//解的个数为2^(自由变元的个数);
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(a,0,sizeof a);
        cin>>n;
        for(int i=0; i<n; i++)
        {
            cin>>b[i];

        }
        for(int i=0; i<n; i++)
        {
            int tmp;
            cin>>tmp;
            a[i][n]=tmp^b[i];//方程等号右边的结果
                a[i][i]=1;
        }
        do
        {
            int p,q;
            cin>>p>>q;
            if(p==0&&q==0) break;
            a[q-1][p-1]=1;//注意交换位置
        }
        while(true);
        int r=Gauss();
        if(r==-1) cout<<"Oh,it's impossible~!!\n";
        else cout<<r<<endl;
    }
    return 0;
}
乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值