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 }

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

时间: 2024-10-03 11:34:56

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

poj 1753 Flip Game 高斯消元

题目链接 4*4的格子, 初始为0或1, 每次翻转一个会使它四周的也翻转, 求翻转成全0或全1最少的步数. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include &

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

poj 1830 开关问题 高斯消元

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

POJ 1166 The Clocks 高斯消元 + exgcd(纯属瞎搞)

根据题意可构造出方程组,方程组的每个方程格式均为:C1*x1 + C2*x2 + ...... + C9*x9 = sum + 4*ki; 高斯消元构造上三角矩阵,以最后一个一行为例: C*x9 = sum + 4*k,exgcd求出符合范围的x9,其他方程在代入已知的变量后格式亦如此. 第一发Gauss,蛮激动的. #include <algorithm> #include <iostream> #include <cstring> #include <cstd

POJ 1830 开关问题 高斯消元,自由变量个数

http://poj.org/problem?id=1830 如果开关s1操作一次,则会有s1(记住自己也会变).和s1连接的开关都会做一次操作. 那么设矩阵a[i][j]表示按下了开关j,开关i会被操作一次,记得a[i][i] = 1是必须的,因为开关i操作一次,本身肯定会变化一次. 所以有n个开关,就有n条方程, 每个开关的操作次数总和是:a[i][1] + a[i][2] + ... + a[i][n] 那么sum % 2就代表它的状态,需要和(en[i] - be[i] + 2) % 2

poj 2947 Widget Factory (高斯消元,解模线性方程)

链接:poj 2947 题意:生产一些零件,已知零件种数,记录条数 记录只记录了某次生产从周几开始,周几结束,以及生产了哪些产品. 每件商品生产所需天数为3-9天. 求每样产品需要多少天才能完成. 若无解输出Inconsistent data. 有无穷解输出Multiple solutions. 有唯一解,输出其解 分析:根据题目所给信息,可以列出同余方程组,再根据高斯消元求解, 但还得判断是无解,无穷解,还是唯一解 1.系数矩阵的秩若与增广矩阵的秩不相等,则无解,否则有解 2.若有解,若增广矩

poj 2947 Widget Factory(高斯消元)

description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to build a widget depends on its type: the simple widgets need only 3 days, but the most complex ones

NEFU 504 new Flip Game (高斯消元)

题目链接 题解:和 poj1753Filp game 差不多,区别在于t组数据并且翻转的时候多了一个左上角. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <map> #includ

poj 3185 The Water Bowls 高斯消元枚举变元

题目链接 给一行0 1 的数, 翻转一个就会使他以及它左右两边的都变, 求最少多少次可以变成全0. 模板题. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include