poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板
题目链接:http://poj.org/problem?id=1222
题意:给出一个5*6的图,每个灯泡有一个初始状态,1表示亮,0表示灭。每对一个灯泡操作时,会影响周围的灯泡改变亮灭,问如何操作可以使得所有灯泡都关掉。
思路:因为每盏灯,如果操作两次就相当于没有操作,所以相当于(操作次数)%2,即异或操作。
考虑一个2*3的图,最后需要的状态是 :,如果初始状态为:
。对这两个矩阵的每个数字做异或操作可以得到线性方程组每个方程的答案。
总共6盏灯,0-5。那么可以列出6个方程。
对于第0盏灯,会影响到它的是第0, 1, 3盏灯,因此可以列出方程1*x0 + 1*x1 + 0*x2 + 1*x3 + 0*x4 + 0*x5= 0。
对于第1盏灯,会影响到它的是第0, 1, 2,4盏灯,因此可以列出方程1*x0 + 1*x1 + 1*x2 + 0*x3 + 1*x4 + 0*x5 = 1。
对于第2盏灯,会影响到它的是第1, 2, 5盏灯,因此可以列出方程0*x0 + 1*x1 + 1*x2 + 0*x3 + 0*x4 + 1*x5 = 0。
.....
所以最后可以列出增广矩阵:
然后用高斯消元求这个矩阵的解就可以了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 #define maxn 8 7 int a[maxn*maxn][maxn*maxn]; 8 int x[maxn*maxn]; 9 int mp[maxn][maxn]; 10 void init() 11 { 12 memset(a, 0, sizeof(a)); 13 for(int i = 0; i < 5; i++) 14 { 15 for(int j = 0; j < 6; j++) 16 { 17 int pos = i*6+j; 18 a[pos][pos] = 1; 19 if(i > 0) a[pos][(i-1)*6+j] = 1; 20 if(i < 4) a[pos][(i+1)*6+j] = 1; 21 if(j > 0) a[pos][i*6+j-1] = 1; 22 if(j < 5) a[pos][i*6+j+1] = 1; 23 } 24 } 25 } 26 void Gauss(int n, int m) 27 { 28 memset(x, 0, sizeof(x)); 29 int r, c; 30 for(r = 0, c = 0; r < n && c < m; r++, c++) 31 { 32 int max_r = r; 33 for(int i = r+1; i < n; i++) 34 { 35 if(fabs(a[i][c]) > fabs(a[max_r][c])) max_r = i; 36 } 37 if(a[max_r][c] == 0) {r--; continue;} 38 if(max_r != r) 39 { 40 for(int i = c; i < m+1; i++) swap(a[max_r][i], a[r][i]); 41 } 42 43 for(int i = r+1; i < n; i++) 44 { 45 if(a[i][c] == 0) continue; 46 for(int j = c; j < m+1; j++) a[i][j] ^= a[r][j]; 47 } 48 } 49 50 for(int i = m-1; i >= 0; i--) 51 { 52 x[i] = a[i][m]; 53 for(int j = i+1; j < m; j++) 54 { 55 x[i] ^= (a[i][j] && x[j]); 56 } 57 } 58 } 59 int main() 60 { 61 // freopen("in.txt", "r", stdin); 62 int T; 63 scanf("%d", &T); 64 int cast = 0; 65 while(T--) 66 { 67 cast++; 68 init(); 69 for(int i = 0; i < 5; i++) 70 { 71 for(int j = 0; j < 6; j++) 72 { 73 scanf("%d", &a[i*6+j][30]); 74 } 75 } 76 Gauss(30, 30); 77 printf("PUZZLE #%d\n", cast); 78 for(int i = 0; i < 5; i++) 79 { 80 for(int j = 0; j < 6; j++) 81 { 82 if(j == 0) printf("%d", x[i*6+j]); 83 else printf(" %d", x[i*6+j]); 84 } 85 printf("\n"); 86 } 87 } 88 return 0; 89 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步