poj1753(高斯消元解mod2方程组)
Posted ygeloutingyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1753(高斯消元解mod2方程组)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=1753
题意:一个 4*4 的棋盘,初始时上面放满了黑色或白色的棋子.对 (i, j) 位置进行一次操作后 (i, j), (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1) 位置的棋子会变成原来相反的状态.问最少需要多少步可以将棋盘上的棋子全部变成白色或者黑色.
思路:分别将棋子变成黑色和白色,然后再用高斯消元解,其中步数较小者即为答案.
注意不存在唯一解时需要枚举自由变元来取得最小步数.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <string.h> 5 using namespace std; 6 7 const int inf = 1e9; 8 const int MAXN = 3e2; 9 int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数 10 int a[MAXN][MAXN];//增广矩正 11 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用) 12 int free_num;//自由变元个数 13 int x[MAXN];//解集 14 15 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数 16 int max_r, col, k; 17 free_num = 0; 18 for(k = 0, col = 0; k < equ && col < var; k++, col++){ 19 max_r = k; 20 for(int i = k + 1; i < equ; i++){ 21 if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i; 22 } 23 if(a[max_r][col] == 0){ 24 k--; 25 free_x[free_num++] = col;//这个是变元 26 continue; 27 } 28 if(max_r != k){ 29 for(int j = col; j < var + 1; j++){ 30 swap(a[k][j], a[max_r][j]); 31 } 32 } 33 for(int i = k + 1; i < equ; i++){ 34 if(a[i][col] != 0){ 35 for(int j = col; j < var + 1; j++){ 36 a[i][j] ^= a[k][j]; 37 } 38 } 39 } 40 } 41 for(int i = k; i < equ; i++){ 42 if(a[i][col] != 0) return -1;//无解 43 } 44 if(k < var) return var - k;//返回自由变元个数 45 for(int i = var - 1; i >= 0; i--){ 46 x[i] = a[i][var]; 47 for(int j = i + 1; j < var; j++){ 48 x[i] ^= (a[i][j] && x[j]); 49 } 50 } 51 return 0; 52 } 53 54 const int n = 4; 55 string s[5]; 56 57 int solve(void){ 58 int op = Gauss(); 59 if(op == -1) return inf;//无解 60 else if(op == 0){//存在唯一解 61 int sol = 0; 62 for(int i = 0; i < var; i++){ 63 sol += x[i]; 64 } 65 return sol; 66 }else{//存在多解,需要枚举自由变元找到最小需要的操作数 67 int sol = inf; 68 int tot = 1 << op;//有op个变元,每个变元可取0或1,共有1<<op总情况 69 for(int i = 0; i < tot; i++){//二进制枚举,i二进制位上为1的取1,为0的取0 70 int cnt = 0; 71 for(int j = 0; j < op; j++){ 72 if(i & (1 << j)){//当前第j位变元取1 73 x[free_x[j]] = 1; 74 cnt++; 75 }else x[free_x[j]] = 0; 76 } 77 for(int j = var - op - 1; j >= 0; j--){ 78 int idx; 79 for(idx = j; idx < var; idx++){ 80 if(a[j][idx]) break; 81 } 82 x[idx] = a[j][var]; 83 for(int l = idx + 1; l < var; l++){ 84 if(a[j][l]) x[idx] ^= x[l]; 85 } 86 cnt += x[idx]; 87 } 88 sol = min(sol, cnt); 89 } 90 return sol; 91 } 92 } 93 94 void f(int op){ 95 for(int i = 0; i < n; i++){ 96 for(int j = 0; j < n; j++){ 97 int cnt = i * n + j; 98 if(s[i][j] == ‘w‘) a[cnt][var] = 1 - op; 99 else a[cnt][var] = op; 100 x[cnt] = 0; 101 } 102 } 103 for(int i = 0; i < equ; i++){//构造增广矩阵 104 int x1 = i / n; 105 int y1 = i % n; 106 for(int j = 0; j < var; j++){ 107 int x2 = j / n; 108 int y2 = j % n; 109 if(abs(x1 - x2) + abs(y1 - y2) < 2) a[j][i] = 1; 110 else a[j][i] = 0; 111 } 112 } 113 } 114 115 void gel(void){ 116 int sol = inf; 117 f(0); 118 sol = min(sol, solve()); 119 f(1); 120 sol = min(sol, solve()); 121 if(sol == inf) cout << "Impossible" << endl; 122 else cout << sol << endl; 123 } 124 125 int main(void){ 126 while(cin >> s[0]){ 127 equ = var = n * n; 128 for(int i = 1; i < n; i++){ 129 cin >> s[i]; 130 } 131 gel(); 132 } 133 return 0; 134 }
以上是关于poj1753(高斯消元解mod2方程组)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2947-Widget Factory(高斯消元解同余方程式)
[POJ1753]Flip Game(异或方程组,高斯消元,枚举自由变量)