[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 }