POJ 1753 Flip Game (高斯消元 枚举自由变元求最小步数)

题目链接

题意:4*4的黑白棋,求把棋全变白或者全变黑的最小步数。

分析:以前用状态压缩做过。 和上题差不多,唯一的不同是这个终态是黑棋或者白棋,

但是只需要把给的初态做不同的两次处理就行了。

感觉现在还只是会套模板,不能独立的思考,好伤心。。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #define LL __int64
  8 const int maxn = 300+10;
  9 const int INF = 1<<28;
 10 using namespace std;
 11 int equ, var, fn;
 12 int a[maxn][maxn], x[maxn];
 13 int free_x[maxn];
 14 int gcd(int a, int b)
 15 {
 16     return b==0?a:gcd(b, a%b);
 17 }
 18 int lcm(int a, int b)
 19 {
 20     return a*b/gcd(a, b);
 21 }
 22 int Gauss()
 23 {
 24     int x_mo;
 25     x_mo = 2;
 26     int i, j, k, max_r, col;
 27     int ta, tb, LCM, fx_num = 0;
 28     col = 0;
 29 
 30     for(k = 0; k<equ && col<var; k++, col++)
 31     {
 32         max_r = k;
 33         for(i = k+1; i < equ; i++)
 34             if(abs(a[i][col])>abs(a[max_r][col]))
 35                 max_r = i;
 36 
 37         if(max_r != k)
 38             for(j = k; j < var+1; j++)
 39                 swap(a[k][j], a[max_r][j]);
 40 
 41         if(a[k][col]==0)
 42         {
 43             free_x[fx_num++] = col; //求自由变元所在的列
 44             k--;
 45             continue;
 46         }
 47         for(i = k+1; i < equ; i++)
 48         {
 49             if(a[i][col] != 0)
 50             {
 51                 LCM = lcm(abs(a[i][col]), abs(a[k][col]));
 52                 ta = LCM/abs(a[i][col]);
 53                 tb= LCM/abs(a[k][col]);
 54                 if(a[i][col]*a[k][col] < 0) tb = -tb;
 55 
 56                 for(j = col; j < var+1; j++)
 57                     a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%x_mo+x_mo)%x_mo;
 58             }
 59         }
 60     }
 61     for(i = k; i < equ; i++)
 62         if(a[i][col] != 0)
 63             return INF;
 64 
 65     int stat=1<<(var-k);
 66     int res=INF;
 67     for(i=0; i<stat; i++)
 68     {
 69         int cnt=0;
 70         int index=i;
 71         for(j=0; j<var-k; j++)
 72         {
 73             x[free_x[j]]=(index&1);
 74             if(x[free_x[j]]) cnt++;
 75             index>>=1;
 76         }
 77         for(j=k-1; j>=0; j--)
 78         {
 79             int tmp=a[j][var];
 80             for(int l=j+1; l<var; l++)
 81                 if(a[j][l]) tmp^=x[l];
 82             x[j]=tmp;
 83             if(x[j])cnt++;
 84         }
 85         if(cnt<res)res=cnt;
 86     }
 87     return res;
 88 }
 89 
 90 void init()
 91 {
 92     int i, j, tmp;
 93     memset(a, 0, sizeof(a));
 94     memset(x, 0, sizeof(x));
 95     for(i = 0; i < 4; i++)
 96         for(j = 0; j < 4; j++)
 97         {
 98             tmp = i*4+j;
 99             a[tmp][tmp] = 1;
100             if(j<=4-2)
101                 a[tmp+1][tmp] = 1;
102             if(j>=1)
103                 a[tmp-1][tmp] = 1;
104             if(tmp+4<4*4)
105                 a[tmp+4][tmp] = 1;
106             if(tmp-4>=0)
107                 a[tmp-4][tmp] = 1;
108         }
109 }
110 int main()
111 {
112     int i, j, ans;
113     char s[maxn][maxn];
114     while(~scanf("%s", s[0]))
115     {
116         equ = 16;
117         var = 16;
118         for(i = 1; i < 4; i++)
119         {
120             getchar();
121             scanf("%s", s[i]);
122         }
123         init();
124         for(i = 0; i < 4; i++)
125             for(j = 0; j < 4; j++)
126             {
127                 if(s[i][j]=='b') a[i*4+j][16] = 0;
128                 else a[i*4+j][16] = 1;
129             }
130         fn = Gauss();
131 
132         init();
133         for(i = 0; i < 4; i++)
134             for(j = 0; j < 4; j++)
135             {
136                 if(s[i][j]=='w') a[i*4+j][16] = 0;
137                 else a[i*4+j][16] = 1;
138             }
139         int fn2 = Gauss();
140         if(fn==INF&&fn2==INF)
141             printf("Impossible\n");
142 
143         else
144         {
145             ans = min(fn, fn2);
146             printf("%d\n", ans);
147         }
148     }
149     return 0;
150 }

 

posted @ 2014-08-19 10:21  水门  阅读(289)  评论(0编辑  收藏  举报