poj1222开关问题

题意:有一个5 * 6的矩阵,每个位置表示灯,1表示灯亮,0表示灯灭。 
然后如果选定位置i,j点击,则位置i,j和其上下左右的灯的状态都会反转。 
现在要你求出一个5 * 6的矩阵,1表示这个灯被点击过,0表示没有。 
要求这个矩阵能够使得原矩阵的灯全灭。 


开始没有理解到说的那个at bt ct 是什么
其实是在A[i][j]按下去的时候他所影响到的 li位置处的状态,这个状态在一个矩阵的M*N 的N M确定之后就随着确定了,不过我没有找到其中的规律,><
然后利用模2加的性质就是相当于异或运算,就可以构造出方程式来出x(i,j)的每一个值
https://blog.csdn.net/u013508213/article/details/47263183

 

#include <iostream>// 用G++,还有就是不能外挂
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
//#define IO  ios::sync_with_stdio(false),cin.tie(0), cout.tie(0);
//#pragma comment(linker, "/STACK:1024000000,1024000000")
void ex_gcd(int a, int b, int &d, int &x, int &y) { if (!b) { x = 1; y = 0; d = a; } else { ex_gcd(b, a%b, d, y, x); y -= x * (a / b); }; }
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
int lcm(int a,int b){return a/gcd(a,b)*b;}//先除后乘防溢出
int inv_exgcd(int a, int m) { int d, x, y;ex_gcd(a, m, d, x, y);return d == 1 ? (x + m) % m : -1; }
typedef long long ll;
const int maxn=1e3;
using namespace std;
int a[maxn][maxn];
int x[maxn];
int n,m;
bool free_x[maxn];//记录不确定的变元
void init()
{
 memset(a,0,sizeof(a));
    for(int i=0;i<5;++i)
        for(int j=0;j<6;++j)///表示对这个A[i][j]确定的上下左右的每个位置的状态进行初始化没有找到其中的规律
    {
        int t=i*6+j;
        a[t][t]=1;
        if(i>0)a[(i-1)*6+j][t]=1;
        if(i<4)a[(i+1)*6+j][t]=1;
        if(j>0)a[i*6+j-1][t]=1;
        if(j<5)a[i*6+j+1][t]=1;
    }
}
int Gauss(int equ,int var)
{
    int max_r,col,k;
    int ta,tb;
    int Lcm;
    int temp;
    int free_x_num=0,free_index;
    for(int i=0;i<=var;++i) x[i]=0,free_x[i]=true;
    //转化为阶梯例
    col=0;//当前列
    for( k=0,col=0;k<equ&&col<var;++k,++col)
    {//枚举当前行
       max_r=k;
       for(int i=k+1;i<equ;++i)
            if(abs(a[i][col])>abs(a[max_r][col]))max_r=i;
       if(max_r!=k)
           for(int i=k;i<=var;++i) swap(a[k][i],a[max_r][i]);///i=0;
        if(!a[k][col])
        {
            k--;
            continue;//处理下一列
        }
      for(int i=k+1;i<equ;++i)
      {//化为阶梯型
          if(a[i][col])
          {
//              Lcm=lcm(abs(a[i][col]),abs(a[k][col]));
//              ta=Lcm/abs(a[i][col]),tb=Lcm/abs(a[k][col]);
//              if(a[i][col]*a[k][col]<0)tb=-tb;
              for(int j=col;j<=var;++j)
              {
                  a[i][j]^=a[k][j];//((a[i][j]*ta-a[k][j]*tb));
              }
          }
      }
    }
    for(int i=k;i<equ;++i)// 无解
        if(a[i][col]) return -1;
    if(k<var)// 无穷解
    {///这这儿可以直接 return var-k;不用求出未知元
//        for(int i=k-1;i>=0;--i)
//        {
//            free_x_num=0;//用于判断不确定性变元的数量,若超过一个仍然无法求解(无解)
//            for(int j=0;j<var;++j)
//                if(a[i][j]&&free_x[j])free_x_num++,free_index=j;
//            if(free_x_num>1)continue;
//            temp=a[i][var];
//            for(int j=0;j<var;++j)
//            {
//                if(a[i][j]&&j!=free_x_num)temp=(temp-a[i][j]*x[j]);
//            }
//            x[free_index]=(temp/a[i][free_index])%7;
//            free_x[free_index]=false;
//        }
        return var-k;
    }
    //唯一解
    for(int i=var-1;i>=0;--i)
    {
        temp=a[i][var];
        for(int j=i+1;j<var;++j)
            if(a[i][j])temp=(temp^(a[i][j]&&x[j]));//cout<<temp<<endl;
        x[i]=temp;
    }
    return 0;
}
int main()
{

    int t;
    cin>>t;
    for(int ca=1;ca<=t;++ca)
    {
        init();
         for(int i=0;i<30;++i)
            scanf("%d",&a[i][30]);
            int free_num=Gauss(30,30);
            printf("PUZZLE #%d\n",ca);
            for(int i=0;i<30;++i)
            {
                printf("%d",x[i]);
                if((i+1)%6==0)
                    printf("\n");
                else
                    printf(" ");
            }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值