POJ 1222 高斯消元更稳

大致题意:

  有5*6个灯,每个灯只有亮和灭两种状态,分别用1和0表示。按下一盏灯的按钮,这盏灯包括它周围的四盏灯都会改变状态,0变成1,1变成0。现在给出5*6的矩阵代表当前状态,求一个能全部使灯灭的解。

分析:

  题目已经提示我们,按两次和按零次是一样的效果,所以每个灯的解为0或者1。这样我们可以构造一个30*30的方程组,右边的常数列为灯的初始状态。

  影响当前灯的状态的按钮有5个

  a[i][j]+x[i][j]+x[i][j-1]+x[i-1][j]+x[i][j+1]+x[i][j+1]=0  (mod 2)

  x[i][j]+x[i][j-1]+x[i-1][j]+x[i][j+1]+x[i][j+1]=a[i][j]  (mod 2)

  不难发现,灯的初始状态只影响常数列,与系数矩阵无关,系数矩阵是不变的。

  消元的过程中系数也可以对2取模,按n次与按n+2次的效果是一样的。对2取模更方便的运算就是异或了。

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

int n=30;
int a[35][35],x[35];
int mat[35][35];

void init()//初始化系数矩阵
{
    int dx[]= {0,0,-1,0,1};
    int dy[]= {0,-1,0,1,0};
    for(int i=1; i<=5; i++)
    {
        for(int j=1; j<=6; j++)
        {
            for(int k=0; k<5; k++)
            {
                int x=i+dx[k];
                int y=j+dy[k];
                if(x>0 && x<=5 && y>0 && y<=6)
                    mat[(i-1)*6+j][(x-1)*6+y]=1;
            }
        }
    }
}

void Gauss(int equ,int var)
{
    int row,col;
    row=col=1;
    while(row<=equ && col<=var)
    {
        //列非零主
        int r=row;
        for(int i=row; i<=equ; i++)
            if(a[i][col]!=0)
            {
                r=i;
                break;
            }
        if(r!=row)
        {
            for(int i=col; i<=var+1; i++)
                swap(a[row][i],a[r][i]);
        }
        if(a[row][col]==0)//说明有自由变元
        {
            col++;
            continue;
        }
        //消元
        for(int i=row+1; i<=equ; i++)
        {
            if(a[i][col]==0) continue;
            for(int j=col; j<=var+1; j++)
                a[i][j]^=a[row][j];
        }
        row++;
        col++;
    }
    for(int i=equ; i>=1; i--)
    {
        x[i]=a[i][var+1];
        for(int j=i+1; j<=var; j++)
            x[i]^=a[i][j]*x[j];
    }
}

int main()
{
    int t,kase=1;
    scanf("%d",&t);
    init();
    while(t--)
    {
        memset(a,0,sizeof(a));
        for(int i=1; i<=30; i++)
            scanf("%d",&a[i][31]);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                a[i][j]=mat[i][j];
        Gauss(n,n);
        printf("PUZZLE #%d\n",kase++);
        for(int i=1; i<=5; i++)
        {
            for(int j=1; j<6; j++)
                printf("%d ",x[(i-1)*6+j]);
            printf("%d\n",x[i*6]);
        }
    }
    return 0;
}
时间: 2024-10-20 17:20:45

POJ 1222 高斯消元更稳的相关文章

*POJ 1222 高斯消元

EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9612   Accepted: 6246 Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons eac

POJ SETI 高斯消元 + 费马小定理

http://poj.org/problem?id=2065 题目是要求 如果str[i] = '*'那就是等于0 求这n条方程在%p下的解. 我看了网上的题解说是高斯消元 + 扩展欧几里德. 然后我自己想了想,就用了高斯消元 + 费马小定理.因为%p是质数,所以很容易就用上了费马小定理,就是在除法的时候用一次就好了.还有就是两个模数相乘还要模一次. #include <cstdio> #include <cstdlib> #include <cstring> #inc

poj 1830 高斯消元

终于会一点高斯消元了,认真学还是学的进去啊...... 搞明白解异或方程的原理,然后构造出矩阵就好做了.模板题 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <stack> 5 #include <queue> 6 #include <map> 7 #include <algorithm> 8 #include <v

POJ 2065-SETI(高斯消元求解同余方程式)

题目地址:POJ 2065 题意:输入一个素数p和一个字符串s(只包含小写字母和'*'),字符串中每个字符对应一个数字,'*'对应0,'a'对应1,'b'对应2.... eg:str[] = "abc", 那么说明 n=3, 字符串所对应的数列为1, 2, 3. 同时题目定义了一个函数:a0*1^0 + a1*1^1+a2*1^2+........+an-1*1^(n-1) = f(1)(mod p), f(1) = str[0] = a = 1; a0*2^0 + a1*2^1+a2

POJ 1222 extended lights out 高斯消元 板子题

题目链接:http://poj.org/problem?id=1222 题目描述:其实就是开关问题, 按下按钮会影响当前和周围的四个按钮, 问关闭所有灯的方案 解题思路:以前用搜索做过, 那时候是刚刚接触ACM的时候, 当时劲头真足啊, 这个解释的很好:http://blog.csdn.net/u013508213/article/details/47263183 代码: #include <iostream> #include <cstdio> #include <cstr

POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)

http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1表示按,0表示不按. 思路:每个开关最多只按一次,因为按了2次之后,就会抵消了. 可以从结果出发,也就是全灭状态怎么按能变成初始状态. 用3*3来举个例子,$X\left ( i,j \right )$表示这些开关是按还是不按,那么对于第一个开关,对它有影响的就只有2.4这两个开关,所以它的异或方程

POJ 1222 EXTENDED LIGHTS OUT(高斯消元)

[题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了数字,周围四格都会发生变化,变化即做一次与1的异或运算,输出每个格子的操作次数. [题解] 高斯消元练手题,对于每个格子的最终情况列一个方程,一共三十个方程三十个未知数,用高斯消元求解即可. [代码] #include <cstdio> #include <algorithm> #in

POJ 1222【异或高斯消元|二进制状态枚举】

题目链接:[http://poj.org/problem?id=1222] 题意:Light Out,给出一个5 * 6的0,1矩阵,0表示灯熄灭,反之为灯亮.输出一种方案,使得所有的等都被熄灭. 题解:首先可以用高斯消元来做,对于每个点,我们列出一个方程,左边是某个点和它相邻的点,他们的异或值等于右边的值(灯亮为1 ,灯灭为0),然后求一个异或高斯消元就可以了.可以用bitset优化,或者__int128优化(其实unsigned就可以了). 还可以枚举第一行的按开关的状态共有1<<6中状态

POJ 1222 EXTENDED LIGHTS OUT 高斯消元

点击打开链接 EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6492   Accepted: 4267 Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 butt