Poj 1753 Flip Game 高斯消元

题目连接:

  http://poj.org/problem?id=1753

题目大意:

  有一个4*4的方格,每个格子是黑色或者白色,每翻转其中一个格子使其变色,将会带动其上下左右的格子同时发生变色,问最终至少要翻转几个格子才能使4*4的方格变成同一种颜色?

解题思路:

  其实这个题目怎么搞都可以,可以暴搜,位运算,dfs,最近在学高斯消元,就用高斯解一下,16个格子增广矩阵列为16*17,求出阶梯矩阵后,枚举不确定变元,根据不确定变元和阶梯矩阵求出确定变元,然后统计需要操作的次数,选择最优即可。

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 const int maxn = 20;
  9 int det[maxn][maxn], equ, var;
 10 
 11 int gauss ()
 12 {
 13     int max_i, k, col, cou = 0;
 14     int free_num[maxn], free_i[maxn], x[maxn];
 15 
 16     memset (free_i, 0, sizeof(free_i));
 17     memset (x, 0, sizeof(x));
 18 
 19     for (k=col=0; k<equ&&col<var; k++, col++)
 20     {//转化为阶梯矩阵
 21         max_i = k;
 22         for (int i=k+1; i<equ; i++)// 找到该col列元素绝对值最大的那行与第k行交换.
 23             if (det[max_i][col] < det[i][col])
 24                 max_i = i;
 25         if (det[max_i][col] == 0)
 26         {// 说明该col列第k行以下全是0了,则处理当前行的下一列.
 27             free_i[col] = 1;
 28             x[cou++] = col;
 29             k --;
 30             continue;
 31         }
 32         if (max_i != k)
 33             for (int i=col; i<=var; i++)
 34                 swap(det[max_i][i], det[k][i]);
 35         for (int i=k+1; i<equ; i++)
 36             if (det[i][col])// 枚举要删去的行.
 37                 for (int j=col; j<=var; j++)
 38                     det[i][j] ^= det[k][j];
 39     }
 40     for (int i=k; i<equ; i++)
 41         if (det[i][var])//判断是否有解
 42             return maxn;
 43     int res = maxn, num = 1<<cou;
 44     for (int i=0; i<num; i++)
 45     {
 46         int nu = 0, m = i;
 47         memset (free_num, 0, sizeof(free_num));
 48         for (int j=0; j<cou; j++)
 49         {//枚举不确定变元
 50             if (m % 2)
 51             {
 52                 free_num[x[j]] = 1;
 53                 nu ++;
 54             }
 55             m /= 2;
 56         }
 57         for (int j=k-1; j>=0; j--)
 58             if (!free_i[j])
 59             {//根据不确定变元,计算确定变元
 60                 int temp = det[j][16];
 61                 for (int l=j+1; l<var; l++)
 62                     if (det[j][l])
 63                         temp ^= free_num[l];
 64                 free_num[j] = temp;
 65                 if (temp)
 66                     nu ++;
 67             }
 68         res = min (res, nu);
 69     }
 70     return res;
 71 }
 72 int main ()
 73 {
 74     int map[maxn], j = 0;
 75     char str[maxn];
 76 
 77     equ = var = 16;
 78     for (int i=0; i<4; i++)
 79     {
 80         scanf ("%s", str);
 81         for (int l=0; str[l]; l++)
 82             if (str[l] == 'b')
 83                 map[j++]=1;
 84             else
 85                 map[j++] = 0;
 86     }
 87 
 88     memset (det, 0, sizeof(det));
 89     for (int i=0; i<16; i++)
 90     {//把方格转化为增广矩阵
 91         det[i][i] = 1;
 92         det[i][16] = map[i];
 93         if (i < 12)
 94             det[i][i+4] = 1;
 95         if (i > 3)
 96             det[i][i-4] = 1;
 97         if (i % 4 != 0)
 98             det[i][i-1] = 1;
 99         if (i % 4 != 3)
100             det[i][i+1] = 1;
101     }
102     int res = gauss ();
103     memset (det, 0, sizeof(det));
104     for (int i=0; i<16; i++)
105     {
106         det[i][i] = 1;
107         det[i][16] = 1 - map[i];
108         if (i < 12)
109             det[i][i+4] = 1;
110         if (i > 3)
111             det[i][i-4] = 1;
112         if (i % 4 != 0)
113             det[i][i-1] = 1;
114         if (i % 4 != 3)
115             det[i][i+1] = 1;
116     }
117     res = min (res, gauss());
118     if (res == maxn)
119         printf ("Impossible\n");
120     else
121         printf ("%d\n", res);
122     return 0;
123 }

顺便再贴一个暴搜代码,简单粗暴,清晰明了

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 
  7 #define N 5
  8 #define INF 0x3f3f3f
  9 using namespace std;
 10 
 11 char a[N][N], map[N][N];
 12 int dir[][2] = {0,0, 1,0, 0,1, -1,0, 0,-1};
 13 
 14 int change(char ch, int num);
 15 void turn (int x, int y, char X[][N]);
 16 void init ();
 17 
 18 int main ()
 19 {
 20     int i, j, min, sum, num;
 21 
 22     for (i=0; i<4; i++)
 23        {
 24             scanf ("%s", a[i]);
 25             strcpy (map[i], a[i]);
 26        }
 27 
 28     min = INF;
 29 
 30     for (i=0; i<16; i++)
 31     {
 32         sum = i;
 33         num = 0;
 34         for (j=0; j<4; j++)
 35         {
 36             if ( sum % 2 )
 37                 {
 38                     turn(0, j, map);
 39                     num ++;
 40                 }
 41             sum /= 2;
 42         }
 43 
 44         init();
 45         sum = change ('b', num);
 46         if (min > sum)
 47             min = sum;
 48         init();
 49         sum = change ('w', num);
 50         if (min > sum)
 51             min = sum;
 52 
 53         sum = i;
 54         for (j=0; j<4; j++)
 55         {
 56             if ( sum % 2 )
 57             {
 58                turn (0, j, map);
 59             }
 60             sum /= 2;
 61         }
 62     }
 63     if (min == INF)
 64         printf ("Impossible\n");
 65     else
 66         printf ("%d\n", min);
 67     return 0;
 68 }
 69 int change( char ch, int num)
 70 {
 71     int i, j;
 72 
 73     for (i=1; i<4; i++)
 74         for (j=0; j<4; j++)
 75             if (a[i-1][j] != ch)
 76             {
 77                 num ++;
 78                 turn(i, j, a);
 79             }
 80     for (i=0; i<4; i++)
 81         if (a[3][i] != ch)
 82            return INF;
 83     return num;
 84 }
 85 
 86 void turn (int x, int y, char X[][N])
 87 {
 88     for (int i=0; i<5; i++)
 89     {
 90         int A = x + dir[i][0];
 91         int B = y + dir[i][1];
 92 
 93         if (A >= 0 && A < 4 && B >= 0 && B < 4)
 94         {
 95             if (X[A][B] == 'w')
 96              X[A][B] = 'b';
 97             else
 98                 X[A][B] = 'w';
 99         }
100     }
101 }
102 
103 void init ()
104 {
105     int i;
106     for (i=0; i<4; i++)
107         strcpy (a[i], map[i]);
108 }

 

posted @ 2015-07-05 11:47  罗茜  阅读(455)  评论(0编辑  收藏  举报