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

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

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

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

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

这几个题目都类似,都可以使用高斯消元来求解一个模2的01方程组来解决。

有时候需要枚举自由变元,有的是判断存不存在解

POJ 1222 EXTENDED LIGHTS OUT

普通的问题。

肯定有唯一解。肯定枚举第一行去做,也可以使用高斯消元。

 /* ***********************************************
Author :kuangbin
Created Time :2013/8/17 18:25:42
File Name :F:\2013ACM练习\专题学习\高斯消元\POJ1222.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std; //对2取模的01方程组
const int MAXN = ;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
int equ,var;
int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元的个数 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss()
{
int max_r,col,k;
free_num = ;
for(k = , col = ; k < equ && col < var ; k++, col++)
{
max_r = k;
for(int i = k+;i < equ;i++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == )
{
k--;
free_x[free_num++] = col;//这个是自由变元
continue;
}
if(max_r != k)
{
for(int j = col; j < var+; j++)
swap(a[k][j],a[max_r][j]);
}
for(int i = k+;i < equ;i++)
{
if(a[i][col] != )
{
for(int j = col;j < var+;j++)
a[i][j] ^= a[k][j];
}
}
}
for(int i = k;i < equ;i++)
if(a[i][col] != )
return -;//无解
if(k < var) return var-k;//自由变元个数
//唯一解,回代
for(int i = var-; i >= ;i--)
{
x[i] = a[i][var];
for(int j = i+;j < var;j++)
x[i] ^= (a[i][j] && x[j]);
}
return ;
}
void init()
{
memset(a,,sizeof(a));
memset(x,,sizeof(x));
equ = ;
var = ;
for(int i = ;i < ;i++)
for(int j = ;j < ;j++)
{
int t = i*+j;
a[t][t] = ;
if(i > )a[(i-)*+j][t] = ;
if(i < )a[(i+)*+j][t] = ;
if(j > )a[i*+j-][t] = ;
if(j < )a[i*+j+][t] = ;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int iCase = ;
scanf("%d",&T);
while(T--)
{
iCase++;
init();
for(int i = ;i < ;i++)
scanf("%d",&a[i][]);
Gauss();
printf("PUZZLE #%d\n",iCase);
for(int i = ;i < ;i++)
{
for(int j = ;j < ;j++)
printf("%d ",x[i*+j]);
printf("%d\n",x[i*+]);
}
}
return ;
}

POJ 1830 开关问题

输出方案数,就是求出有多少个自由变元就可以了。

 /* ***********************************************
Author :kuangbin
Created Time :2013/8/17 19:44:33
File Name :F:\2013ACM练习\专题学习\高斯消元\POJ1830.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
//对2取模的01方程组
const int MAXN = ;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
int equ,var;
int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元的个数 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss()
{
int max_r,col,k;
free_num = ;
for(k = , col = ; k < equ && col < var ; k++, col++)
{
max_r = k;
for(int i = k+;i < equ;i++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == )
{
k--;
free_x[free_num++] = col;//这个是自由变元
continue;
}
if(max_r != k)
{
for(int j = col; j < var+; j++)
swap(a[k][j],a[max_r][j]);
}
for(int i = k+;i < equ;i++)
{
if(a[i][col] != )
{
for(int j = col;j < var+;j++)
a[i][j] ^= a[k][j];
}
}
}
for(int i = k;i < equ;i++)
if(a[i][col] != )
return -;//无解
if(k < var) return var-k;//自由变元个数
//唯一解,回代
for(int i = var-; i >= ;i--)
{
x[i] = a[i][var];
for(int j = i+;j < var;j++)
x[i] ^= (a[i][j] && x[j]);
}
return ;
}
void init()
{
memset(a,,sizeof(a));
memset(x,,sizeof(x));
}
int start[MAXN],end[MAXN]; int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = ;i < n;i++)
scanf("%d",&start[i]);
for(int i = ;i < n;i++)
scanf("%d",&end[i]);
init();
equ = var = n;
for(int i = ;i < n;i++)
a[i][i] = ;
int u,v;
while(scanf("%d%d",&u,&v) == )
{
if(u == && v == )break;
a[v-][u-] = ;
}
for(int i = ;i < n;i++)
a[i][n] = (start[i]^end[i]);
int ans = Gauss();
if(ans == -)
printf("Oh,it's impossible~!!\n");
else printf("%d\n",(<<ans));
}
return ;
}

POJ 1681 Painter's Problem

需要步数最少的,要枚举自由变元求解。

 /* ***********************************************
Author :kuangbin
Created Time :2013/8/17 19:56:07
File Name :F:\2013ACM练习\专题学习\高斯消元\POJ1681.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
//对2取模的01方程组
const int MAXN = ;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
int equ,var;
int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元的个数 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss()
{
int max_r,col,k;
free_num = ;
for(k = , col = ; k < equ && col < var ; k++, col++)
{
max_r = k;
for(int i = k+;i < equ;i++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == )
{
k--;
free_x[free_num++] = col;//这个是自由变元
continue;
}
if(max_r != k)
{
for(int j = col; j < var+; j++)
swap(a[k][j],a[max_r][j]);
}
for(int i = k+;i < equ;i++)
{
if(a[i][col] != )
{
for(int j = col;j < var+;j++)
a[i][j] ^= a[k][j];
}
}
}
for(int i = k;i < equ;i++)
if(a[i][col] != )
return -;//无解
if(k < var) return var-k;//自由变元个数
//唯一解,回代
for(int i = var-; i >= ;i--)
{
x[i] = a[i][var];
for(int j = i+;j < var;j++)
x[i] ^= (a[i][j] && x[j]);
}
return ;
}
int n;
void init()
{
memset(a,,sizeof(a));
memset(x,,sizeof(x));
equ = n*n;
var = n*n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
{
int t = i*n+j;
a[t][t] = ;
if(i > )a[(i-)*n+j][t] = ;
if(i < n-)a[(i+)*n+j][t] = ;
if(j > )a[i*n+j-][t] = ;
if(j < n-)a[i*n+j+][t] = ;
}
}
void solve()
{
int t = Gauss();
if(t == -)
{
printf("inf\n");
return;
}
else if(t == )
{
int ans = ;
for(int i = ;i < n*n;i++)
ans += x[i];
printf("%d\n",ans);
return;
}
else
{
//枚举自由变元
int ans = 0x3f3f3f3f;
int tot = (<<t);
for(int i = ;i < tot;i++)
{
int cnt = ;
for(int j = ;j < t;j++)
{
if(i&(<<j))
{
x[free_x[j]] = ;
cnt++;
}
else x[free_x[j]] = ;
}
for(int j = var-t-;j >= ;j--)
{
int idx;
for(idx = j;idx < var;idx++)
if(a[j][idx])
break;
x[idx] = a[j][var];
for(int l = idx+;l < var;l++)
if(a[j][l])
x[idx] ^= x[l];
cnt += x[idx];
}
ans = min(ans,cnt);
}
printf("%d\n",ans);
}
}
char str[][];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i = ;i < n;i++)
{
scanf("%s",str[i]);
for(int j = ;j < n;j++)
{
if(str[i][j] == 'y')
a[i*n+j][n*n] = ;
else a[i*n+j][n*n] = ;
}
}
solve();
}
return ;
}

POJ 1753 Flip Game

数据范围很小,随便搞,也是要枚举自由变元。。。。这题用高斯消元真是杀鸡用牛刀了

 /* ***********************************************
Author :kuangbin
Created Time :2013/8/17 20:53:13
File Name :F:\2013ACM练习\专题学习\高斯消元\POJ1753.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
//对2取模的01方程组
const int MAXN = ;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
int equ,var;
int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元的个数 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss()
{
int max_r,col,k;
free_num = ;
for(k = , col = ; k < equ && col < var ; k++, col++)
{
max_r = k;
for(int i = k+;i < equ;i++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == )
{
k--;
free_x[free_num++] = col;//这个是自由变元
continue;
}
if(max_r != k)
{
for(int j = col; j < var+; j++)
swap(a[k][j],a[max_r][j]);
}
for(int i = k+;i < equ;i++)
{
if(a[i][col] != )
{
for(int j = col;j < var+;j++)
a[i][j] ^= a[k][j];
}
}
}
for(int i = k;i < equ;i++)
if(a[i][col] != )
return -;//无解
if(k < var) return var-k;//自由变元个数
//唯一解,回代
for(int i = var-; i >= ;i--)
{
x[i] = a[i][var];
for(int j = i+;j < var;j++)
x[i] ^= (a[i][j] && x[j]);
}
return ;
}
int n;
void init()
{
memset(a,,sizeof(a));
memset(x,,sizeof(x));
equ = n*n;
var = n*n;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
{
int t = i*n+j;
a[t][t] = ;
if(i > )a[(i-)*n+j][t] = ;
if(i < n-)a[(i+)*n+j][t] = ;
if(j > )a[i*n+j-][t] = ;
if(j < n-)a[i*n+j+][t] = ;
}
}
const int INF = 0x3f3f3f3f;
int solve()
{
int t = Gauss();
if(t == -)
{
return INF;
}
else if(t == )
{
int ans = ;
for(int i = ;i < n*n;i++)
ans += x[i];
return ans;
}
else
{
//枚举自由变元
int ans = INF;
int tot = (<<t);
for(int i = ;i < tot;i++)
{
int cnt = ;
for(int j = ;j < t;j++)
{
if(i&(<<j))
{
x[free_x[j]] = ;
cnt++;
}
else x[free_x[j]] = ;
}
for(int j = var-t-;j >= ;j--)
{
int idx;
for(idx = j;idx < var;idx++)
if(a[j][idx])
break;
x[idx] = a[j][var];
for(int l = idx+;l < var;l++)
if(a[j][l])
x[idx] ^= x[l];
cnt += x[idx];
}
ans = min(ans,cnt);
}
return ans;
}
}
char str[][];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
n = ;
for(int i = ;i < ;i++)
scanf("%s",str[i]);
init();
for(int i = ;i < ;i++)
for(int j = ;j < ;j++)
{
if(str[i][j] == 'b')a[i*+j][] = ;
else a[i*+j][] = ;
}
int ans1 = solve();
init();
for(int i = ;i < ;i++)
for(int j = ;j < ;j++)
{
if(str[i][j] == 'b')a[i*+j][] = ;
else a[i*+j][] = ;
}
int ans2 = solve();
if(ans1 == INF && ans2 == INF)
printf("Impossible\n");
else printf("%d\n",min(ans1,ans2));
return ;
}

POJ 3185 The Water Bowls

一维的了,更简单的还是枚举比较好。

高斯消元随便搞

 /* ***********************************************
Author :kuangbin
Created Time :2013/8/17 21:53:09
File Name :F:\2013ACM练习\专题学习\高斯消元\POJ3185.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
//对2取模的01方程组
const int MAXN = ;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var
int equ,var;
int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元的个数 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss()
{
int max_r,col,k;
free_num = ;
for(k = , col = ; k < equ && col < var ; k++, col++)
{
max_r = k;
for(int i = k+;i < equ;i++)
{
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == )
{
k--;
free_x[free_num++] = col;//这个是自由变元
continue;
}
if(max_r != k)
{
for(int j = col; j < var+; j++)
swap(a[k][j],a[max_r][j]);
}
for(int i = k+;i < equ;i++)
{
if(a[i][col] != )
{
for(int j = col;j < var+;j++)
a[i][j] ^= a[k][j];
}
}
}
for(int i = k;i < equ;i++)
if(a[i][col] != )
return -;//无解
if(k < var) return var-k;//自由变元个数
//唯一解,回代
for(int i = var-; i >= ;i--)
{
x[i] = a[i][var];
for(int j = i+;j < var;j++)
x[i] ^= (a[i][j] && x[j]);
}
return ;
}
void init()
{
memset(a,,sizeof(a));
memset(x,,sizeof(x));
equ = ;
var = ;
for(int i = ;i < ;i++)
{
a[i][i] = ;
if(i > ) a[i-][i] = ;
if(i < )a[i+][i] = ;
}
}
void solve()
{
int t = Gauss();
if(t == -)
{
printf("inf\n");
return;
}
else if(t == )
{
int ans = ;
for(int i = ;i < ;i++)
ans += x[i];
printf("%d\n",ans);
return;
}
else
{
//枚举自由变元
int ans = 0x3f3f3f3f;
int tot = (<<t);
for(int i = ;i < tot;i++)
{
int cnt = ;
for(int j = ;j < t;j++)
{
if(i&(<<j))
{
x[free_x[j]] = ;
cnt++;
}
else x[free_x[j]] = ;
}
for(int j = var-t-;j >= ;j--)
{
int idx;
for(idx = j;idx < var;idx++)
if(a[j][idx])
break;
x[idx] = a[j][var];
for(int l = idx+;l < var;l++)
if(a[j][l])
x[idx] ^= x[l];
cnt += x[idx];
}
ans = min(ans,cnt);
}
printf("%d\n",ans);
}
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
init();
for(int i = ;i < ;i++)
scanf("%d",&a[i][]);
solve();
return ;
}

专题:

高斯消元解方程:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=29538#overview

POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题的更多相关文章

  1. POJ 1681 Painter's Problem(高斯消元+枚举自由变元)

    http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...

  2. POJ 1681 Painter's Problem 【高斯消元 二进制枚举】

    任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total ...

  3. POJ 1830 开关问题(高斯消元求解的情况)

    开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 8714   Accepted: 3424 Description ...

  4. poj 1681 Painter&#39;s Problem(高斯消元)

    id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...

  5. POJ 1681 Painter's Problem (高斯消元 枚举自由变元求最小的步数)

    题目链接 题意: 一个n*n 的木板 ,每个格子 都 可以 染成 白色和黄色,( 一旦我们对也个格子染色 ,他的上下左右 都将改变颜色): 给定一个初始状态 , 求将 所有的 格子 染成黄色 最少需要 ...

  6. POJ 1753 Flip game ( 高斯消元枚举自由变量)

    题目链接 题意:给定一个4*4的矩阵,有两种颜色,每次反转一个颜色会反转他自身以及上下左右的颜色,问把他们全变成一种颜色的最少步数. 题解:4*4的矩阵打表可知一共有四个自由变元,枚举变元求最小解即可 ...

  7. poj 1753 Flip Game 高斯消元

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

  8. POJ 2065 高斯消元求解问题

    题目大意: f[k] = ∑a[i]*k^i % p 每一个f[k]的值就是字符串上第 k 个元素映射的值,*代表f[k] = 0 , 字母代表f[k] = str[i]-'a'+1 把每一个k^i求 ...

  9. POJ 1222 EXTENDED LIGHTS OUT(高斯消元)

    [题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...

随机推荐

  1. Mysql存储之原生语句操作(pymysql)

    Mysql存储之原生语句操作(pymysql) 关系型数据库是基于关系模型的数据库,而关系模型是通过二维表时实现的,于是构成了行列的表结构. 表可以看作是某个实体的集合,而实体之间存在联系,这个就需要 ...

  2. [转载]FFmpeg完美入门[3] - FFmpeg功能及使用说明

    1 ffplay对多媒体的支持能力验证 一.视频3gp 177X144 支持播放,在windows下播放正常,但是在linux下面偶有BUG 如果发现画面无法显示而声音可以播放的情况下可以试着切换全屏 ...

  3. 部署weblogic 12c的几点收获

    最近刚编写完weblogic12c的部署脚本,这里将过程中的几点收获进行记录: 1.windows下编写的脚本在linux环境下运行需要dos2unix进行格式转换 2.weblogic安装环境检测需 ...

  4. python模块之xml.etree.ElementTree

    xml.etree.ElementTree用于解析和构建XML文件 <?xml version="1.0"?> <data> <country nam ...

  5. acm专题--并查集

    题目来源:http://hihocoder.com/problemset/problem/1066 #1066 : 无间道之并查集 时间限制:20000ms 单点时限:1000ms 内存限制:256M ...

  6. C++中求类的大小

    今天刷题时看到一题,是求类的大小的,其中涉及了内存的一些知识,记录一下. 正确答案是12和9 首先是内存对齐原则,可以参考这篇博文:http://www.cppblog.com/snailcong/a ...

  7. mongodb与mysql传统的关系数据库区别

    转自:易百教程 MongoDB中的数据具有灵活的模式.文档在同一集合,但它们不需要具有相同的字段或结构集合,集合文档中的公共字段可以包含不同类型的数据. MongoDB中的数据具有灵活的模式.与SQL ...

  8. csu 1806 & csu 1742 (simpson公式+最短路)

    1806: Toll Time Limit: 5 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 256  Solved: 74[Submit][Sta ...

  9. ie8浏览器 图片本身问题导致 无法显示图片--- 诡异现象的排查分享

    引子:   前段时间 做新版2.0 首页 的时候, 总感觉 新版首页 线上 精彩回顾下的 2张图片颜色怪怪的,当时以为是图片压缩太厉害导致的,由于实在太忙就没太在意!以下 是来自线上 截图:  红色方 ...

  10. 洛谷P4171 [JSOI2010] 满汉全席 [2-SAT,Tarjan]

    题目传送门 满汉全席 题目描述 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉 ...