为了学习高斯消元写了下这一题,代码是按照维基百科的伪代码来写的,每个点的状态和他自己以及周围五个点是否按下有关,于是只要每个点作为一个未知数,列出30个方程,用高斯消元求解即可。
其实这题完全可以不必用高斯消元,枚举第一行的状态就可以了,第一行的状态可以决定第二行的状态,进而就可以决定整幅图的状态。
1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <stdlib.h> 5 int cas,n,m,x[50][50],ans[31]; 6 void gauss(){ 7 int i=1,j=1; 8 while(i<=n&&j<=m){ 9 int maxi=i; 10 for(int k=i+1;k<=n;k++) 11 if(abs(x[k][j])>abs(x[maxi][j]))maxi=k; 12 if(x[maxi][j]){ 13 for(int k=1;k<=m;k++)std::swap(x[i][k],x[maxi][k]); 14 for(int k=j,div=x[i][j];k<=m;k++)x[i][k]/=div; 15 for(int k1=i+1;k1<=n;k1++) 16 for(int k2=j,y=x[k1][j];k2<=m;k2++) 17 x[k1][k2]-=y*x[i][k2],x[k1][k2]=x[k1][k2]%2; 18 i++; 19 } 20 j++; 21 } 22 ans[31]=1; 23 for(int i=n;i>=1;i--){ 24 int tmp=0; 25 for(int j=i+1;j<=31;j++) 26 tmp+=ans[j]*x[i][j]; 27 ans[i]=(tmp%2+2)%2; 28 } 29 } 30 31 int main(){ 32 //freopen("test.in","r",stdin); 33 scanf("%d",&cas); 34 for(int ca=1;ca<=cas;ca++){ 35 memset(x,0,sizeof x); 36 n=30,m=31; 37 for(int i=1;i<=30;i++){ 38 x[i][i]=x[i][i-6]=x[i][i+6]=1; 39 if(i%6!=1)x[i][i-1]=1; 40 if(i%6!=0)x[i][i+1]=1; 41 } 42 for(int i=1;i<=30;i++)scanf("%d",&x[i][31]); 43 gauss(); 44 printf("PUZZLE #%d\n",ca); 45 for(int i=1;i<=30;i++){ 46 printf("%d",ans[i]); 47 printf(i%6?" ":"\n"); 48 } 49 } 50 return 0; 51 }