POJ 1222 EXTENDED LIGHTS OUT 关灯游戏-高斯消元(列主元)

题意:关灯游戏,给出一个状态,求关灯方案。

题解:由于控制矩阵是确定的,并且是满秩的,所以解唯一。

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

#define MAXN 30
int a[MAXN][MAXN], b[MAXN];

int Gauss ( int n, int a[][MAXN], int b[] )
{
    int i, j, k, row;
    for ( k = 0; k < n; k++ )
    {
        for ( i = k; i < n; i++ )
            if ( a[i][k] == 1 ) { row = i; break; }
        if ( i == n ) return 0; //由于控制矩阵可逆,所以x[]是有唯一解的,此处也可省略

        if ( row != k )
        {
            for ( j = k; j < n; j++ )
                swap ( a[k][j], a[row][j] );
            swap ( b[k], b[row] );
        }

        for ( i = k + 1; i < n; i++ )
        {
            if ( a[i][k] == 0 ) continue; //按行处理
            for ( j = k + 1; j < n; j++ )
                a[i][j] ^= a[k][j];
            b[i] ^= b[k];
        }
    }

    b[n-1] = b[n-1] / a[n-1][n-1];
    for ( i = n - 2; i >= 0; i-- )
    {
        for ( j = i + 1; j < n; j++ )
            b[i] ^= ( a[i][j] * b[j] );
        b[i] = b[i] / a[i][i];
    }
    return 1;
}


void init ()
{
    int i, j;
    int t1, t2, t3, t4;
    for ( i = 0; i < 30; i++ )
    {
        t1 = i / 6;
        t2 = i % 6;
        for ( j = 0; j < 30; j++ )
        {
            t3 = j / 6;
            t4 = j % 6;
            if ( abs(t1-t3) + abs(t2-t4) <= 1 )
                a[i][j] = 1;
            else a[i][j] = 0;
        }
    }
   
}

int main()
{
    int t, k, i;
    scanf("%d",&t);
    for ( k = 1; k <= t; k++ )
    {
        for ( i = 0; i < 30; i++ )
            scanf("%d",&b[i]);

        init();
        Gauss ( 30, a, b );
        printf("PUZZLE #%d\n",k);
        for ( i = 1; i <= 30; i++ )
        {
            printf("%d ", b[i-1]);
            if ( i % 6 == 0 ) printf("\n");
        }
    }
    return 0;
}



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

#define MAXN 30
int a[MAXN][MAXN], b[MAXN];

int Gauss ( int n, int a[][MAXN], int b[] )
{
    int i, j, k, row;
    for ( k = 0; k < n; k++ )
    {
        for ( i = k; i < n; i++ )
            if ( a[i][k] == 1 ) { row = i; break; }
        if ( i == n ) return 0; //由于控制矩阵可逆,所以x[]是有唯一解的,此处也可省略

        if ( row != k )
        {
            for ( j = k; j < n; j++ )
                swap ( a[k][j], a[row][j] );
            swap ( b[k], b[row] );
        }


        for ( j = k + 1;j < n; j++ )  //按列处理
            for ( i = k + 1; i < n; i++ )
                a[i][j] ^= ( a[i][k] * a[k][j] ); // a[i][j] ^= ( a[i][k] / a[k][k] * a[k][j] ); a[k][k] == 1;
        for ( i = k + 1; i < n; i++ )
            b[i] ^= ( a[i][k] * b[k] );
    }

    //b[n-1] = b[n-1] / a[n-1][n-1]; a[n-1][n-1] == 1;
    for ( i = n - 2; i >= 0; i-- )
    {
        for ( j = i + 1; j < n; j++ )
            b[i] ^= ( a[i][j] * b[j] );
        //b[i] = b[i] / a[i][i];
    }
    return 1;
}


void init ()
{
    int i, j;
    int t1, t2, t3, t4;
    for ( i = 0; i < 30; i++ )
    {
        t1 = i / 6;
        t2 = i % 6;
        for ( j = 0; j < 30; j++ )
        {
            t3 = j / 6;
            t4 = j % 6;
            if ( abs(t1-t3) + abs(t2-t4) <= 1 )
                a[i][j] = 1;
            else a[i][j] = 0;
        }
    }

}

int main()
{
    int t, k, i;
    scanf("%d",&t);
    for ( k = 1; k <= t; k++ )
    {
        for ( i = 0; i < 30; i++ )
            scanf("%d",&b[i]);

        init();
        Gauss ( 30, a, b );
        printf("PUZZLE #%d\n",k);
        for ( i = 1; i <= 30; i++ )
        {
            printf("%d ", b[i-1]);
            if ( i % 6 == 0 ) printf("\n");
        }
    }
    return 0;
}


你可能感兴趣的:(游戏)