之前的博客好像有点水
做法
上面已经讲过,另一种写法是先消成倒三角状,在从下往上一个个解出未知数。
对于无解的情况:
有n个未知数,大于n个方程发现后面的方程未知数元已经被消掉可是增广矩阵的右边还有值,则判无解。另外,消元时发现某一行所有元被消掉可是增广矩阵的右边还有值,则判无解。
对于有无穷解的情况:
从下往上解方程时发现可能有无穷解,那么先把可以求出解的方程算出来,再对那些还不能求出解的方程求解,如果发现系数为0,则就有无穷解
例题
Description
有一个有趣的手机游戏,有n*n个正方形的小按钮,有的按钮是黄色,有的按钮是白色。玩家的任务是通过点击按钮,让所有按钮都变成黄色,点按钮的次数越少,得分越高。
但是按钮有个奇怪的特点,当你点击了坐标为(x,y)的按钮后,坐标为(x,y),(x+1,y),(x-1,y),(x,y-1),(x,y+1)的五个按钮会同时改变自身的颜色,是白色的变成黄色,黄色的变成白色。完成游戏最少需要点击多少次按钮呢?请找出答案。
Input
第一行,一个整数n,表示有n*n个按钮。(1<=n<=40)
接下来是一个由小写字母'y'和字符'w'构成的n*n的矩阵,描述了游戏开始时的情景。'y'表示该按钮式黄色,'w'表示该按钮式白色。
Output
如果能够完成游戏,输出一个整数,表示所需最小点击次数。
如果无法完成游戏,输出"inf"
Sample Input
样例输入1: 2 yw ww 样例输入2: 5 wwwww wwwww wwwww wwwww wwwww
Sample Output
样例输出1: 1 样例输出2: 15
直接高斯消元mod 2 方程组每一个格子只可能有5个格子通过操作使这个格子变换,所以时间复杂度是5n^2的
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 43;
int n;
int sum[MAXN*MAXN][MAXN*MAXN];
char s[MAXN];
int qz( int x , int y ){ return ( x - 1 ) * n + y ; }
int ans = 0x3f3f3f3f , tot[MAXN];
void dfs( int x , int now ){
if( !x ){
ans = min( ans , now );
return ;
}
int k = 0;
for( int i = x + 1 ; i <= n * n ; i ++ ){
k = ( k + tot[i] * sum[x][i] % 2 ) % 2;
}
if( !sum[x][x] && k != sum[x][n*n+1] ){
printf( "inf" );
exit(0);
}
if( !sum[x][x] ){
tot[x] = 1;dfs( x - 1, now + 1 );
tot[x] = 0;dfs( x - 1 , now );
}
else if( sum[x][x] && k == sum[x][n*n+1] ){
tot[x] = 0;dfs( x - 1 , now );
}
else{
tot[x] = 1;dfs( x - 1 , now + 1 );
}
}
int main(){
scanf( "%d" , &n );
for( int i = 1 ; i <= n ; i ++ ){
scanf( "%s" , s );
for( int j = 0 ; j < n ; j ++ ){
if( s[j] == 'y' )
sum[qz(i,j+1)][n*n+1] = 0;
else sum[qz(i,j+1)][n*n+1] = 1;
}
}
for( int i = 1 ; i <= n ; i ++ ){
for( int j = 1 ; j <= n ; j ++ ){
if( i - 1 >= 1 ){
sum[qz(i,j)][qz(i-1,j)] = 1;
}
if( j - 1 >= 1 )
sum[qz(i,j)][qz(i,j-1)] = 1;
sum[qz(i,j)][qz(i,j)] = 1;
if( j + 1 <= n )
sum[qz(i,j)][qz(i,j+1)] = 1;
if( i + 1 <= n )
sum[qz(i,j)][qz(i+1,j)] = 1;
}
}
for( int i = 1 ; i <= n * n ; i ++ ){
if( !sum[i][i] ){
for( int j = i + 1 ; j <= n * n ; j ++ )
if( sum[j][i] ){
for( int k = 1 ; k <= n * n + 1 ; k ++ )
swap( sum[i][k] , sum[j][k] );
break;
}
}
for( int j = i + 1 ; j <= n * n ; j ++ ){
if( sum[j][i] ){
for( int k = 1 ; k <= n * n + 1 ; k ++ ){
sum[j][k] = ( sum[j][k] - sum[i][k] + 2 ) % 2;
}
}
}
}
dfs( n * n , 0 );
printf( "%d" , ans );
return 0;
}