1. 程式人生 > >高斯消元以poj1222為例

高斯消元以poj1222為例

tin 組成 sub ac代碼 題目 iostream tdi pre 變亮

【題目鏈接】

  http://poj.org/problem?id=1222

【題目大意】
  5*6的一個由燈組成的方陣 操作一個燈 周圍的上下左右四個燈會發生相應變化 即由滅變亮 由亮變滅 問如何操作使燈全亮

【題解】

  對於每個燈可以列出一個方程

  Lk表示第 k 個燈的初始終狀態

  ai:表示第 i 個開關是否對 Lk 有影響

  xj:表示第 j 個開關的狀態

L1 XOR a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = 0

L2 XOR a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = 0

……

L30 XOR a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = 0

解上述異或方程組即可得到答案。

為了方便求解,可將上述方程組變形,兩邊同時異或Lk (由於0^a = a),得:

a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = L1

a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = L2

  ……

a1 *x1 XOR a2*x2 XOR a3*x3 XOR …… XOR a29*x29 XOR a30x30 = L30

【ac代碼】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 
  6 int a[35][35];    //增廣矩陣 
  7 int x[35];        //線性方程組的解 
  8 int equ;        //方程個數 
  9 int var;        //變量個數 
 10 
 11 void init()
 12 {
 13     memset(x, 0, sizeof(x));
 14
memset(a, 0, sizeof(a)); 15 } 16 17 void Gauss() 18 { 19 int row, col, i, j; 20 row = col = 0; 21 22 while(row<equ && col<var) 23 { 24 for(i=row; i<equ; ++i) //選出row~equ行中第一個為1的那一行 25 { 26 if(a[i][col] != 0) break; 27 } 28 if(i != row) //兩行交換 29 { 30 for(j=col;j<=var;++j) 31 { 32 swap(a[row][j], a[i][j]); 33 } 34 } 35 if(a[row][col]==0) //無法消元,繼續下一個變量 36 { 37 ++col; 38 continue; 39 } 40 41 for(int i=row+1;i<equ;++i) //消元 42 { 43 if(a[i][col]==0) continue; 44 for(int j=col;j<=var;++j) 45 { 46 a[i][j] ^= a[row][j]; 47 } 48 } 49 ++row; 50 ++col; 51 } 52 53 for(i=var-1;i>=0;--i) //回代求解 54 { 55 x[i] = a[i][var]; 56 for(j=i+1;j<var;++j) 57 { 58 x[i] ^= (a[i][j]&&x[j]); //回代關鍵步驟 59 } 60 } 61 } 62 63 int main() 64 { 65 int t; 66 int num; 67 scanf("%d", &t); 68 for(int item=1; item<=t; ++item) 69 { 70 init(); 71 for(int i=0;i<30;++i) 72 { 73 scanf("%d", &a[i][30]); 74 } 75 76 for(int i=0;i<5;++i) //確定方程組的系數 77 { //a[i][j]的意義:第j個開關能否控制第i個燈 78 for(int j=0;j<6;++j) 79 { 80 int num = i*6+j; 81 a[num][num] = 1; 82 if(i>=1) 83 { 84 a[num-6][num] = 1; 85 } 86 if(i<=3) 87 { 88 a[num+6][num] = 1; 89 } 90 if(j-1 >= 0) 91 { 92 a[num-1][num] = 1; 93 } 94 if(j+1 <= 5) 95 { 96 a[num+1][num] = 1; 97 } 98 } 99 } 100 101 equ = 30; 102 var = 30; 103 104 Gauss(); 105 printf("PUZZLE #%d\n", item); 106 for(int i=0;i<30;++i) 107 { 108 if(i%6==5) //控制每行輸出6個 109 { 110 printf("%d", x[i]); 111 printf("\n"); 112 } 113 else 114 { 115 printf("%d ", x[i]); 116 } 117 } 118 } 119 return 0; 120 }

【模板】:後續更新

高斯消元以poj1222為例