zoj 3353 Chess Board 高斯消元

来源:互联网 发布:北京握奇数据系统待遇 编辑:程序博客网 时间:2024/05/16 01:23

高斯消元其本应用:

这题是要枚举自由元的;


#include<iostream>#include<cstring>#include<cstdio>#define M 250using 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 );}}}


原创粉丝点击