POJ 1222 EXTENDED LIGHTS OUT [高斯消元]

  为了学习高斯消元写了下这一题,代码是按照维基百科的伪代码来写的,每个点的状态和他自己以及周围五个点是否按下有关,于是只要每个点作为一个未知数,列出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 }
posted @ 2012-08-31 19:22  Burn_E  阅读(276)  评论(0编辑  收藏  举报