高斯消元其本应用:
这题是要枚举自由元的;
#include<iostream>
#include<cstring>
#include<cstdio>
#define M 250
using namespace std;
int mat[M][M], ans[M], rem[M];
int id[20][20], num;
int n, m;
int dx[8] = {-1,-1,-1,0,0,1,1,1};
int dy[8] = {-1,0,1,-1,1,-1,0,1};
int d[4][5] = {1,3,4,6,-1,0,1,3,4,5,1,2,3,4,6,1,2,3,6,7}; //每一种pattern的走法;
bool inside( int i, int j )
{
if( i >= 0 && i < n && j >= 0 && j < m )
return 1;
return 0;
}
void init( int a ) //初始化矩阵
{
int en, u, v, x, y, w;
memset( mat, 0, sizeof(mat) );
if( a ) en = 5;
else en = 4;
for( int i = 0; i < n; i++ )
for( int j = 0; j < m; j++ ){
u = id[i][j];
mat[u][u] = 1;
mat[u][num] = rem[u];
for( int k = 0; k < en; k++ ){
w = d[a][k];
x = i + dx[w];
y = j + dy[w];
if( inside( x, y ) ){
v = id[x][y];
mat[v][u] = 1;
}
}
}
}
int cal( int row )
{
for( int i = row-1; i >= 0; i-- ){
ans[i] = mat[i][num];
for( int j = i+1; j < num; j++ )
ans[i] ^= mat[i][j]*ans[j];
}
int sum = 0;
for( int i = 0; i < num; i++ )
sum += ans[i];
return sum;
}
int gauss( int aa )
{
init(aa);
int row = 0, col = 0;
int i, j, a, b;
while( row < num && col < num ){
for( i = row; i < num; i++ )
if( mat[i][col] ) break;
if( i == num ){
col++; continue;
}
if( i != row ){
for( j = col; j <= num; j++ )
swap( mat[i][j], mat[row][j] );
}
if( row != col ){ //列交换相当于把变量的位置交换,不影响结果。是为了方便把所有自由元排在后面
for( j = 0; j < num; j++ )
swap( mat[j][row], mat[j][col] );
}
for( i = row + 1; i < num; i++ ){
if( mat[i][row] == 0 ) continue;
for( j = row; j <= num; j++ ){
mat[i][j] ^= mat[row][j]; //这里的异或操作只适用于只有0和1的情况
}
}
row++; col++;
}
for( i = row; i < num; i++ )
if( mat[i][num] ) return -1;
int free = num - row;
int len = 1<<free;
a = M;
for( i = 0; i < len; i++ ){ //枚举自由元的答案
for( j = 0; j < free; j++ )
ans[num-j-1] = (i&(1<<j)) != 0;
b = cal( row );
a = min( a, b );
}
return a;
}
int main()
{
char str[M];
int ma, k, temp;
while( scanf( "%d%d", &n, &m ) == 2 ){
if( !n && !m ) break;
num = 0;
for( int i = 0; i < n; i++ ){
scanf( "%s", str );
for( int j = 0; j < m; j++ ){
rem[num] = (str[j] == '1');
id[i][j] = num++;
}
}
ma = M;k = -1;
for( int i = 0; i < 4; i++ ){
temp = gauss( i );
if( temp != -1 && temp < ma ){
ma = temp;
k = i+1;
}
}
if( ma == M )
printf( "Impossible\n" );
else{
printf( "%d %d\n", k, ma );
}
}
}