poj 1753 Flip Game 高斯消元 异或方程组 求最值

题目链接: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
");
147         else printf("%d
", min(sum1, sum2));
148 
149     }
150     return 0;
151 }
原文地址:https://www.cnblogs.com/titicia/p/5397084.html