poj1753(高斯消元解mod2方程组)

题目链接:http://poj.org/problem?id=1753

题意:一个 4*4 的棋盘,初始时上面放满了黑色或白色的棋子.对 (i, j) 位置进行一次操作后 (i, j), (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1) 位置的棋子会变成原来相反的状态.问最少需要多少步可以将棋盘上的棋子全部变成白色或者黑色.

思路:分别将棋子变成黑色和白色,然后再用高斯消元解,其中步数较小者即为答案.

注意不存在唯一解时需要枚举自由变元来取得最小步数.

代码:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <algorithm>
  4 #include <string.h>
  5 using namespace std;
  6
  7 const int inf = 1e9;
  8 const int MAXN = 3e2;
  9 int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数
 10 int a[MAXN][MAXN];//增广矩正
 11 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
 12 int free_num;//自由变元个数
 13 int x[MAXN];//解集
 14
 15 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数
 16     int max_r, col, k;
 17     free_num = 0;
 18     for(k = 0, col = 0; k < equ && col < var; k++, col++){
 19         max_r = k;
 20         for(int i = k + 1; i < equ; i++){
 21             if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i;
 22         }
 23         if(a[max_r][col] == 0){
 24             k--;
 25             free_x[free_num++] = col;//这个是变元
 26             continue;
 27         }
 28         if(max_r != k){
 29             for(int j = col; j < var + 1; j++){
 30                 swap(a[k][j], a[max_r][j]);
 31             }
 32         }
 33         for(int i = k + 1; i < equ; i++){
 34             if(a[i][col] != 0){
 35                 for(int j = col; j < var + 1; j++){
 36                     a[i][j] ^= a[k][j];
 37                 }
 38             }
 39         }
 40     }
 41     for(int i = k; i < equ; i++){
 42         if(a[i][col] != 0) return -1;//无解
 43     }
 44     if(k < var) return var - k;//返回自由变元个数
 45     for(int i = var - 1; i >= 0; i--){
 46         x[i] = a[i][var];
 47         for(int j = i + 1; j < var; j++){
 48             x[i] ^= (a[i][j] && x[j]);
 49         }
 50     }
 51     return 0;
 52 }
 53
 54 const int n = 4;
 55 string s[5];
 56
 57 int solve(void){
 58     int op = Gauss();
 59     if(op == -1) return inf;//无解
 60     else if(op == 0){//存在唯一解
 61         int sol = 0;
 62         for(int i = 0; i < var; i++){
 63             sol += x[i];
 64         }
 65         return sol;
 66     }else{//存在多解,需要枚举自由变元找到最小需要的操作数
 67         int sol = inf;
 68         int tot = 1 << op;//有op个变元,每个变元可取0或1,共有1<<op总情况
 69         for(int i = 0; i < tot; i++){//二进制枚举,i二进制位上为1的取1,为0的取0
 70             int cnt = 0;
 71             for(int j = 0; j < op; j++){
 72                 if(i & (1 << j)){//当前第j位变元取1
 73                     x[free_x[j]] = 1;
 74                     cnt++;
 75                 }else x[free_x[j]] = 0;
 76             }
 77             for(int j = var - op - 1; j >= 0; j--){
 78                 int idx;
 79                 for(idx = j; idx < var; idx++){
 80                     if(a[j][idx]) break;
 81                 }
 82                 x[idx] = a[j][var];
 83                 for(int l = idx + 1; l < var; l++){
 84                     if(a[j][l]) x[idx] ^= x[l];
 85                 }
 86                 cnt += x[idx];
 87             }
 88             sol = min(sol, cnt);
 89         }
 90         return sol;
 91     }
 92 }
 93
 94 void f(int op){
 95     for(int i = 0; i < n; i++){
 96         for(int j = 0; j < n; j++){
 97             int cnt = i * n + j;
 98             if(s[i][j] == ‘w‘) a[cnt][var] = 1 - op;
 99             else a[cnt][var] = op;
100             x[cnt] = 0;
101         }
102     }
103     for(int i = 0; i < equ; i++){//构造增广矩阵
104         int x1 = i / n;
105         int y1 = i % n;
106         for(int j = 0; j < var; j++){
107             int x2 = j / n;
108             int y2 = j % n;
109             if(abs(x1 - x2) + abs(y1 - y2) < 2) a[j][i] = 1;
110             else a[j][i] = 0;
111         }
112     }
113 }
114
115 void gel(void){
116     int sol = inf;
117     f(0);
118     sol = min(sol, solve());
119     f(1);
120     sol = min(sol, solve());
121     if(sol == inf) cout << "Impossible" << endl;
122     else cout << sol << endl;
123 }
124
125 int main(void){
126     while(cin >> s[0]){
127         equ = var = n * n;
128         for(int i = 1; i < n; i++){
129             cin >> s[i];
130         }
131         gel();
132     }
133     return 0;
134 }

时间: 2024-08-15 10:17:53

poj1753(高斯消元解mod2方程组)的相关文章

poj1830(高斯消元解mod2方程组)

题目链接:http://poj.org/problem?id=1830 题意:中文题诶- 思路:高斯消元解 mod2 方程组 有 n 个变元,根据给出的条件列 n 个方程组,初始状态和终止状态不同的位置对应的方程右边常数项为1,状态相同的位置对于的方程组右边的常数项为0.然后用高斯消元解一下即可.若有唯一解输出1即可,要是存在 k 个变元,则答案为 1 << k, 因为每个变元都有01两种选择嘛- 代码: 1 #include <iostream> 2 #include <s

POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)

http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1表示按,0表示不按. 思路:每个开关最多只按一次,因为按了2次之后,就会抵消了. 可以从结果出发,也就是全灭状态怎么按能变成初始状态. 用3*3来举个例子,$X\left ( i,j \right )$表示这些开关是按还是不按,那么对于第一个开关,对它有影响的就只有2.4这两个开关,所以它的异或方程

POJ 2065 SETI(高斯消元解模方程组)

题目: SETI Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1693   Accepted: 1054 Description For some years, quite a lot of work has been put into listening to electromagnetic radio signals received from space, in order to understand what

【高斯消元解xor方程】BZOJ1923-[Sdoi2010]外星千足虫

[题目大意] 有n个数或为奇数或为偶数,现在进行m次操作,每次取出部分求和,告诉你这几次操作选取的数和它们和的奇偶性.如果通过这m次操作能得到所有数的奇偶性,则输出进行到第n次时即可求出答案:否则输出无法确定. [思路] 高斯消元解xor方程组,求最少需要的方程个数或判断无法确定. 无法确定即存在自由元,在每次操作中找1的时候判断一下就好了:最小方程个数,就是记录下每次找到的最小的1的位置,最后输出最大值即可. [错误] 忘记把ans改为-1了(见程序注释) [备注] P.S.我看别人在高斯消元

BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组

题目大意:给出一个无向图,问删掉k条边的时候,图是否联通. 思路:虽然我把这两个题放在了一起,但是其实这两个题可以用完全不同的两个解法来解决. 第一个题其实是DZY出错了...把每次的边数也异或了,那就直接用这个性质一个一个往后推就行了..最后一个暴力求一下.. 第二个题才是本意啊. 听到做法的时候我惊呆了.. 首先是将整个图中拆出一个树,那么所有边就分为树边和非树边.将所有非树边都加一个随机权值.树边的权值是所有能够覆盖它的非树边的权值的异或和. 把整个图拆开的充要条件是拆掉一条树边,同时将所

POJ2947Widget Factory(高斯消元解同模方程)

http://poj.org/problem?id=2947 题目大意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,即ai=aj).规定每件装饰物至少生产3 天,最多生产9 天.问每种装饰物需要生产的天数.如果没有解,

【高斯消元解XOR方程】POJ1222-EXTENDED

[题目大意] 有5*6盏灯,每次开/关一个灯,上下左右的灯状态也会反转.问怎么使状态统一? [思路] 典型高斯消元解XOR方程,注意每盏灯要么0次要么1次. 1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <set> 5 using namespace std; 6 int a[40][40]; 7 void gauss() 8 { 9 int i,j,

poj2947(高斯消元解同模方程组)

题目链接:http://poj.org/problem?id=2947 题意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下: p start enda1, a2......ap (1<= ai <= n)第一行表示从星期 start 到星期 end 一共生产了p 件装饰物 (工作的天数为end - start + 1 + 7*x, 加 7*x 是因为它可能生产很多周),第二行表示这 p 件装饰物的种类(可能出现相同的种类,即 ai = aj).规定每件装饰物至少生产3 天,最多生产9

【BZOJ2466】【中山市选2009】树 高斯消元解异或方程组

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44356273"); } 题解: 参照此题解,也是我写的,俩题一样. [POJ1681]Painter's Problem 高斯消元,求最小∑系数的异或方程组 代码: #include <cmath> #include &