题目链接:http://poj.org/problem?id=1753
题意:给出一张4*4的图,表示16个方格的初始颜色的情况(白或黑),相邻方格操作的时候会相互影响,求最少的操作次数,使得每个方格都是白色或者都是黑色,如果不行输出Impossible。
思路:和poj1222差不多,这题要求最值,所以要枚举自由变元的值。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 #define maxn 5 7 char mp[maxn][maxn]; 8 int a[maxn*maxn][maxn*maxn]; 9 int x[maxn*maxn]; 10 int free_x[maxn*maxn]; 11 int free_num; 12 int mj_ans; 13 #define inf 0x3f3f3f3f 14 void init() 15 { 16 memset(a, 0, sizeof(a)); 17 for(int i = 0; i < 4; i++) 18 { 19 for(int j = 0; j < 4; j++) 20 { 21 int pos = i*4+j; 22 a[pos][pos] = 1; 23 if(i > 0) a[pos][(i-1)*4+j] = 1; 24 if(i < 3) a[pos][(i+1)*4+j] = 1; 25 if(j > 0) a[pos][i*4+j-1] = 1; 26 if(j < 3) a[pos][i*4+j+1] = 1; 27 } 28 } 29 } 30 int Gauss(int n, int m) 31 { 32 memset(x, 0, sizeof(x)); 33 int r, c; 34 free_num = 0; 35 for(r = 0, c = 0; r < n && c < m; r++, c++) 36 { 37 int max_r = r; 38 for(int i = r+1; i < n; i++) 39 { 40 if(fabs(a[i][c]) > fabs(a[max_r][c])) max_r = i; 41 } 42 if(a[max_r][c] == 0) {r--; free_x[free_num++] = c; continue;} 43 if(max_r != r) 44 { 45 for(int i = c; i < m+1; i++) swap(a[r][i], a[max_r][i]); 46 } 47 48 for(int i = r+1; i < n; i++) 49 { 50 if(a[i][c] == 0) continue; 51 for(int j = c; j < m+1; j++) 52 { 53 a[i][j] ^= a[r][j]; 54 } 55 } 56 } 57 for(int i = r; i < n; i++) 58 { 59 if(a[i][c]) return -1; 60 } 61 if(r < m) 62 { 63 mj_ans = inf; 64 int cnt = m-r; 65 for(int i = 0; i < (1<<cnt); i++) 66 { 67 int sum = 0; 68 for(int j = 0; j < cnt; j++) 69 { 70 if(i&(1<<j)) {x[free_x[j]] = 1; sum++;} 71 else x[free_x[j]] = 0; 72 } 73 for(int j = m-1-cnt; j >= 0; j--) 74 { 75 int pos; 76 for(pos = j; pos < m; pos++) if(a[j][pos]) break; 77 x[pos] = a[j][m]; 78 for(int k = pos+1; k < m; k++) 79 { 80 x[pos] ^= (a[j][k] && x[k]); 81 } 82 if(x[pos]) sum++; 83 } 84 if(sum < mj_ans) mj_ans = sum; 85 } 86 return m-r; 87 } 88 for(int i = m-1; i >= 0; i--) 89 { 90 x[i] = a[i][m]; 91 for(int j = i+1; j < m; j++) 92 { 93 x[i] ^= (a[i][j] && x[j]); 94 } 95 } 96 return 0; 97 } 98 int main() 99 { 100 101 //freopen("in.txt", "r", stdin); 102 while(~scanf("%s", mp[0])) 103 { 104 for(int i = 1; i < 4; i++) scanf("%s", mp[i]); 105 106 init(); 107 for(int i = 0; i < 4; i++) 108 { 109 for(int j = 0; j < 4; j++) 110 { 111 if(mp[i][j] == 'b') a[i*4+j][16] = 1; 112 } 113 } 114 int cnt = Gauss(16, 16); 115 int sum1 = 0, sum2 = 0; 116 if(cnt == -1) sum1 = inf; 117 else if(cnt == 0) 118 { 119 for(int i = 0; i < 16; i++) 120 { 121 if(x[i]) sum1++; 122 } 123 } 124 else sum1 = mj_ans; 125 126 127 init(); 128 for(int i = 0; i < 4; i++) 129 { 130 for(int j = 0; j < 4; j++) 131 { 132 if(mp[i][j] == 'w') a[i*4+j][16] = 1; 133 } 134 } 135 cnt = Gauss(16, 16); 136 if(cnt == -1) sum2 = inf; 137 else if(cnt == 0) 138 { 139 for(int i = 0; i < 16; i++) 140 { 141 if(x[i]) sum2++; 142 } 143 } 144 else sum2 = mj_ans; 145 146 if(min(sum1, sum2) == inf) printf("Impossible\n"); 147 else printf("%d\n", min(sum1, sum2)); 148 149 } 150 return 0; 151 }