zoukankan      html  css  js  c++  java
  • 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
    ");
    120     else
    121         printf ("%d
    ", 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
    ");
     65     else
     66         printf ("%d
    ", 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 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    ACM-ICPC 2018 南京赛区网络预赛J. Sum
    ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze(分层dijkstra)
    51nod1246 罐子和硬币
    UVALive
    CodeForces
    CodeForces
    hdu3861(tarjan缩点+最小路径覆盖)
    hdu1072(dfs和bfs)
    51nod1352 集合计数(扩展欧几里得)
    Cmder如何调整命令行字体大小
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4621918.html
Copyright © 2011-2022 走看看