POJ 1222-EXTENDED LIGHTS OUT解题报告
链接:http://poj.org/problem?id=1222
这题是说有5*6个开关,0处于关闭状态,1处于开启状态,每按一个开关,周围的上下左右方向的开关会跟着翻转,而且题目中给了提示,任何一个开关,按偶数次和不按的作用是一样的,所以每个开关最多转换一次,问的是如何转换能达到全部都为关闭状态。我们可以知道,任意一个位置的开关由自己和周围的开关共同决定,那么可以对每一个开关建立一个方程,这样就有30个方程,30个未知数,一定有解,利用高斯消元加位运算可以解出每个未知数。
View Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N 30 5 using namespace std; 6 int a[N][N]; 7 int x[N]; 8 int n; 9 int Abs(int a) 10 { 11 return a<0?-a:a; 12 } 13 void guass() 14 { 15 int i,j,k,row; 16 n=30; 17 for(k=0;k<n;k++)//一次缩减矩阵的阶数 18 { 19 for(i=k;i<n;i++)//对每一个未知数找到第一个本列是1的方程 20 if(a[i][k]==1) 21 { 22 row=i; 23 break; 24 } 25 if(row!=k)//交换原来的列和第一个本列是1的方程,构成行阶梯型原始状态 26 { 27 for(j=k;j<n;j++) 28 { 29 swap(a[i][j],a[k][j]); 30 } 31 swap(x[i],x[k]); 32 } 33 for(i=k+1;i<n;i++)//行阶梯型的化简 34 { 35 if(a[i][k]==0) 36 continue; 37 for(j=k+1;j<n;j++) 38 a[i][j]^=a[k][j]; 39 x[i]^=x[k]; 40 } 41 } 42 x[n-1]/=a[n-1][n-1]; 43 for(i=n-2;i>=0;i--)//求解过程 44 { 45 for(j=i+1;j<n;j++) 46 x[i]^=(x[j]*a[i][j]); 47 x[i]/=a[i][i]; 48 } 49 } 50 void init()//方程未知数的系数 51 { 52 int i,j,t1,t2,t3,t4; 53 for(i=0;i<30;i++) 54 { 55 t1=i/6; 56 t2=i%6; 57 for(j=0;j<30;j++) 58 { 59 t3=j/6; 60 t4=j%6; 61 if(Abs(t3-t1)+Abs(t4-t2)<=1) 62 a[i][j]=1; 63 else 64 a[i][j]=0; 65 } 66 } 67 } 68 int main() 69 { 70 int t,i,j,k; 71 scanf("%d",&t); 72 for(k=1;k<=t;k++) 73 { 74 for(i=0;i<30;i++) 75 scanf("%d",&x[i]); 76 init(); 77 guass(); 78 printf("PUZZLE #%d\n",k); 79 for(i=0;i<5;i++) 80 { 81 for(j=0;j<6;j++) 82 { 83 if(j) 84 printf(" "); 85 printf("%d",x[i*6+j]); 86 } 87 printf("\n"); 88 } 89 } 90 return 0; 91 }