首页 > 代码库 > [POJ1753]Flip Game(异或方程组,高斯消元,枚举自由变量)

[POJ1753]Flip Game(异或方程组,高斯消元,枚举自由变量)

题目链接:http://poj.org/problem?id=1753

题意:同上。

这回翻来翻去要考虑自由变元了,假设返回了自由变元数量,则需要枚举自由变元。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <algorithm>
 18 #include <iostream>
 19 #include <iomanip>
 20 #include <cstring>
 21 #include <climits>
 22 #include <complex>
 23 #include <cassert>
 24 #include <cstdio>
 25 #include <bitset>
 26 #include <vector>
 27 #include <deque>
 28 #include <queue>
 29 #include <stack>
 30 #include <ctime>
 31 #include <set>
 32 #include <map>
 33 #include <cmath>
 34 using namespace std;
 35 
 36 const int maxn = 230;
 37 int equ, var;
 38 int a[maxn][maxn];
 39 int x[maxn];
 40 int free_x[maxn];
 41 int free_num;
 42 int ret1, ret2;
 43 
 44 int gauss() {
 45     int max_r, col, k;
 46     free_num = 0;
 47     for(k = 0, col = 0; k < equ && col < var; k++, col++) {
 48         max_r = k;
 49         for(int i = k + 1; i < equ; i++) {
 50             if(abs(a[i][col]) > abs(a[max_r][col]))
 51                 max_r = i;
 52         }
 53         if(a[max_r][col] == 0) {
 54             k--;
 55             free_x[free_num++] = col;
 56             continue;
 57         }
 58         if(max_r != k) {
 59             for(int j = col; j < var + 1; j++)
 60                 swap(a[k][j], a[max_r][j]);
 61         }
 62         for(int i = k + 1; i < equ; i++) {
 63             if(a[i][col] != 0) {
 64                 for(int j = col; j < var + 1; j++) {
 65                     a[i][j] ^= a[k][j];
 66                 }
 67             }
 68         }
 69     }
 70     for(int i = k; i < equ; i++) {
 71         if(a[i][col] != 0)
 72             return -1;
 73     }
 74     if(k < var) return var - k;
 75     for(int i = var - 1; i >= 0; i--) {
 76         x[i] = a[i][var];
 77         for(int j = i + 1; j < var; j++) {
 78             x[i] ^= (a[i][j] & x[j]);
 79         }
 80     }
 81     return 0;
 82 }
 83 
 84 char G[maxn][maxn];
 85 int n;
 86 
 87 int main() {
 88     // freopen("in", "r", stdin);
 89     n = 4;
 90     var = equ = 16;
 91     ret1 = ret2 = 0;
 92     memset(a, 0, sizeof(a));
 93     for(int i = 0; i < n; i++) scanf("%s", G[i]);
 94     for(int i = 0; i < n; i++) {
 95         for(int j = 0; j < n; j++) {
 96             if(G[i][j] == b) a[i*n+j][var] = 1;
 97             else a[i*n+j][var] = 0;
 98         }
 99     }
100     for(int i = 0; i < n; i++) {
101         for(int j = 0; j < n; j++) {
102             int q = i * n + j;
103             a[q][q] = 1;
104             if(i > 0) a[(i-1)*n+j][q] = 1;
105             if(i < n - 1) a[(i+1)*n+j][q] = 1;
106             if(j > 0) a[i*n+j-1][q] = 1;
107             if(j < n - 1) a[i*n+j+1][q] = 1;
108         }
109     }
110     int v1 = gauss();
111     if(v1 == -1) ret1 = -1;
112     else if(v1 != 0) {
113         ret1 = maxn;
114         int tot = 1 << v1;
115         for(int i = 0; i < tot; i++) {
116             int cnt = 0;
117             for(int j = 0; j < v1; j++) {
118                 if(i&(1<<j)) {
119                     x[free_x[j]] = 1;
120                     cnt++;
121                 }
122                 else x[free_x[j]] = 0;
123             }
124             for(int j = var - v1 - 1; j >= 0; j--) {
125                 int idx;
126                 for(idx = j; idx < var; idx++) {
127                     if(a[j][idx]) break;
128                 }
129                 x[idx] = a[j][var];
130                 for(int l = idx + 1; l < var; l++) {
131                     if(a[j][l]) x[idx] ^= x[l];
132                 }
133                 cnt += x[idx];
134             }
135             ret1 = min(ret1, cnt);
136         }
137     }
138     else for(int i = 0; i < var; i++) ret1 += x[i];
139 
140     memset(a, 0, sizeof(a));
141     for(int i = 0; i < n; i++) {
142         for(int j = 0; j < n; j++) {
143             if(G[i][j] == w) a[i*n+j][var] = 1;
144             else a[i*n+j][var] = 0;
145         }
146     }
147     for(int i = 0; i < n; i++) {
148         for(int j = 0; j < n; j++) {
149             int q = i * n + j;
150             a[q][q] = 1;
151             if(i > 0) a[(i-1)*n+j][q] = 1;
152             if(i < n - 1) a[(i+1)*n+j][q] = 1;
153             if(j > 0) a[i*n+j-1][q] = 1;
154             if(j < n - 1) a[i*n+j+1][q] = 1;
155         }
156     }
157 
158     int v2 = gauss();
159     if(v2 == -1) ret2 = -1;
160     else if(v2 != 0) {
161         ret2 = maxn;
162         int tot = 1 << v2;
163         for(int i = 0; i < tot; i++) {
164             int cnt = 0;
165             for(int j = 0; j < v2; j++) {
166                 if(i&(1<<j)) {
167                     x[free_x[j]] = 1;
168                     cnt++;
169                 }
170                 else x[free_x[j]] = 0;
171             }
172             for(int j = var - v2 - 1; j >= 0; j--) {
173                 int idx;
174                 for(idx = j; idx < var; idx++) {
175                     if(a[j][idx]) break;
176                 }
177                 x[idx] = a[j][var];
178                 for(int l = idx + 1; l < var; l++) {
179                     if(a[j][l]) x[idx] ^= x[l];
180                 }
181                 cnt += x[idx];
182             }
183             ret2 = min(ret2, cnt);
184         }
185     }
186     else for(int i = 0; i < var; i++) ret2 += x[i];
187     if(ret1==-1&&ret2==-1) puts("Impossible");
188     else if(v1==-1) printf("%d\n", ret2);
189     else if(ret2==-1) printf("%d\n", ret1);
190     else printf("%d\n", min(ret1, ret2));
191     return 0;
192 }

 

[POJ1753]Flip Game(异或方程组,高斯消元,枚举自由变量)