题目原文
高斯消元,这是我一直很纠结的,上学期一直不敢写,主要是觉得这个模拟太麻烦了,很烦,也没有看看别人怎么写的。但是这学期校赛的时候,我竟然遇到的第一道题目就是高斯消元,当时就怒了,我们队三人没有一个会写的,靠!当时那个无语啊,血都气的吐出来了。比赛后那天晚上,连夜写了一个高斯消元的模板出来,第二天狂AC五道题,还是不能解恨。
这是一道经典的高斯消元的开关问题,具体怎么写的就不在做详细的说明了,直接上代码
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #define N 35 #define INF 100000000 #define EPS 1e-7 using namespace std; const int zl[4][2]={1,0,-1,0,0,1,0,-1}; bool ok(int x,int y) { if(x>=0 && x<5 && y>=0 && y<6) return true; return false; } int gcd(int a,int b) { int t; while(b!=0) { t=b; b=a%b; a=t; } return a; } int lcm(int a,int b) { return a*b/gcd(a,b); } int gauss(int aug[][N],int n,int m,int x[]) { int row=0,col=0; for(;row<n,col<m;row++,col++) { int max_r=-1; for(int i=row;i<n;i++) if(fabs(aug[i][col])>0) { max_r=i; break; } if(max_r!=row) for(int i=0;i<m+1;i++) swap(aug[max_r][i],aug[row][i]); if(aug[row][col]==0) { row--; continue; } for(int i=row+1;i<n;i++) { if(aug[i][col]!=0) { int LCM=lcm(fabs(aug[i][col]),fabs(aug[row][col])); int ta=LCM/fabs(aug[i][col]),tb=LCM/fabs(aug[row][col]); if(aug[i][col]*aug[row][col]<0) tb=-tb; // 异号的情况是两个数相加. for(int j=col;j<m+1;j++) { aug[i][j]=(aug[i][j]*ta-aug[row][j]*tb)%2; } } } } for(int i=row;i<n;i++) if(aug[i][col]!=0) return -1; if(n-row!=0) return n-row; for(int i=row-1;i>=0;i--) { int temp=aug[i][m]; for(int j=i+1;j<m;j++) temp-=x[j]*aug[i][j]; x[i]=(temp)/aug[i][i]; } return 0; } int main() { int t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { int aug[N][N]; memset(aug,0,sizeof(aug)); int button[7][7]; for(int i=0;i<5;i++) for(int j=0;j<6;j++) scanf("%d",&button[i][j]); int g[7][7]; int n,m;//n个方程,m个变元 那么增广矩阵有m+1列 n=m=30; for(int i=0;i<5;i++) for(int j=0;j<6;j++) { aug[i*6+j][i*6+j]=1; for(int k=0;k<4;k++) if(ok(i+zl[k][0],j+zl[k][1])) aug[i*6+j][(i+zl[k][0])*6+(j+zl[k][1])]=1; } for(int i=0;i<5;i++) for(int j=0;j<6;j++) if(button[i][j]==1) aug[i*6+j][30]=1; else aug[i*6+j][30]=0; int x[30]; memset(x,0,sizeof(x)); printf("PUZZLE #%d\n",ca); int ans=gauss(aug,30,30,x); for(int i=0;i<30;i++) { int now=fabs(((int)x[i])%2); printf("%d",now); if((i+1)%6==0) printf("\n"); else printf(" "); } } return 0; }