[Gauss]POJ1753 Flip Game

题意:给4×4的棋盘的初始状态,b代表黑,w代表白。

要求变成全黑或者全白 最少需要几步。

简单的做法 可以暴搜 状压bfs 不再赘述 

主要学习Gauss做法

同样是01方程组 用异或解

注意全黑或全白都可以

即 bbbb        wwww

    bbbb        wwww

  bbbb        wwww

  bbbb        wwww      这两种的步数步数都是0.

因此我的做法是 列两个方程组分别求最小步数,再取最小值

  1 int a[300][300];  // 增广矩阵
  2 int b[300][300];
  3 int x[300];  //
  4 int free_x[300]; // 标记是否为自由未知量
  5 
  6 int n;
  7 void debug()
  8 {
  9     for(int i0=0;i0<n*n;i0++)
 10     {
 11         for(int j0=0;j0<n*n;j0++)
 12             printf("%d ", a[i0][j0]);
 13         printf("
");
 14     }
 15 }
 16 
 17 int Gauss(int n, int m) // n个方程 m个未知数 即 n行m+1列
 18 {
 19     //转换为阶梯形式
 20     int col=0, k, num=0;
 21     for(k=0;k<n && col<m;k++, col++)
 22     {//枚举行
 23         int max_r=k;
 24         for(int i=k+1;i<n;i++)//找到第col列元素绝对值最大的那行与第k行交换
 25             if(abs(a[i][col])>abs(a[max_r][col]))
 26                 max_r=i;
 27         if(max_r!=k)// 与第k行交换
 28             for(int j=col;j<m+1;j++)
 29                 swap(a[k][j], a[max_r][j]);
 30         if(!a[k][col])// 说明该col列第k行以下全是0了
 31         {
 32             k--;
 33             free_x[num++]=col;
 34             continue;
 35         }
 36         for(int i=k+1;i<n;i++)// 枚举要删除的行
 37             if(a[i][col])
 38                 for(int j=col;j<m+1;j++)
 39                     a[i][j]^=a[k][j];
 40     }
 41 
 42 //    debug();
 43 //    printf("%d %d
", col, k);
 44 
 45     for(int i=k;i<n;i++)
 46         if(a[i][col])
 47             return -1; // 无解
 48 
 49 //    if(k<m)   //m-k为自由未知量个数
 50 //    {
 51         int stat=1<<(m-k);
 52         int ans=INT_MAX;
 53         for(int i=0;i<stat;i++)
 54         {
 55             int cnt=0;
 56             for(int j=0;j<m-k;j++)
 57                 if(i&(1<<j))
 58                 {
 59                     x[free_x[j]]=1;
 60                     cnt++;
 61                 }
 62                 else
 63                     x[free_x[j]]=0;
 64             for(int j=k-1;j>=0;j--)
 65             {
 66                 int tmp;
 67                 for(tmp=j;tmp<m;tmp++)
 68                     if(a[j][tmp])
 69                         break;
 70                 x[tmp]=a[j][m];
 71                 for(int l=tmp+1;l<m;l++)
 72                     if(a[j][l])
 73                         x[tmp]^=x[l];
 74                 cnt+=x[tmp];
 75             }
 76             if(cnt<ans)
 77                 ans=cnt;
 78         }
 79         return ans;
 80 //    }
 81 
 82 //    //  唯一解 回代
 83 //    for(int i=m-1;i>=0;i--)
 84 //    {
 85 //        x[i]=a[i][m];
 86 //        for(int j=i+1;j<m;j++)
 87 //            x[i]^=(a[i][j] && x[j]);
 88 //    }
 89 //    int ans=0;
 90 //    for(int i=0;i<n*n;i++)
 91 //        ans+=x[i];
 92 //    return ans;
 93 }
 94 
 95 
 96 void init()
 97 {
 98     n=4;
 99     memset(a, 0, sizeof(a));
100     memset(x, 0, sizeof(x));
101     for(int i=0;i<n;i++)
102         for(int j=0;j<n;j++)
103         {
104             int t=i*n+j;
105             a[t][t]=1;
106             if(i>0)
107                 a[(i-1)*n+j][t]=1;
108             if(i<n-1)
109                 a[(i+1)*n+j][t]=1;
110             if(j>0)
111                 a[i*n+j-1][t]=1;
112             if(j<n-1)
113                 a[i*n+j+1][t]=1;
114         }
115 }
116 
117 int main()
118 {
119     char ch;
120     while(cin>>ch)
121     {
122         init();
123         a[0][16]=(ch=='b');
124         b[0][16]=(ch=='w');
125         for(int i=1;i<16;i++)
126         {
127             cin>>ch;
128             a[i][n*n]=(ch=='b');
129             b[i][n*n]=(ch=='w');
130         }
131         int t=Gauss(n*n, n*n);
132         if(t==-1)
133         {
134             printf("Impossible
");
135             continue ;
136         }
137         init();
138         for(int i=0;i<16;i++)
139             a[i][16]=b[i][16];
140         int tt=Gauss(n*n, n*n);
141         printf("%d
", min(t, tt));
142     }
143     return 0;
144 }
POJ 1753
原文地址:https://www.cnblogs.com/Empress/p/4248083.html