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. 32.Longest Valid Parentheses---dp

    题目链接:https://leetcode.com/problems/longest-valid-parentheses/description/ 题目大意:找出最长的括号匹配的子串长度.例子:&qu ...

  2. html的loadrunner脚本2

    Action(){ char buf[1911]; //¶¨Òå×Ö·ûÊý×飬Ö÷ÒªÓÃÓÚдÈëXML±¨Îĵ½»º³åÇø char str_Body[4086]; //³Ð½Ó±¨Î ...

  3. Python 库汇总英文版

    Awesome Python  A curated list of awesome Python frameworks, libraries, software and resources. Insp ...

  4. Codefroces 735D Taxes(哥德巴赫猜想)

    题目链接:http://codeforces.com/problemset/problem/735/D 题目大意:给一个n,n可以被分解成n1+n2+n3+....nk(1=<k<=n). ...

  5. int类中的方法(二)

        25.__pos__(self,*args,**kwargs) def __pos__(self, *args, **kwargs): # real signature unknown &qu ...

  6. .NET基本权限系统框架源代码

    DEMO下载地址: 百度网盘:http://pan.baidu.com/s/147ilj http://download.csdn.net/detail/shecixiong/5372895 一.开发 ...

  7. Building Robust and Flexible Event System in Unity3D

    Building Robust and Flexible Event System in Unity3D 1. Prerequisites 1.1 Observer Pattern According ...

  8. javascript入门教程笔记

    BOM BOM 是“ Browser Object Model ”的缩写,简称“ 浏览器对象模型 ”. BOM 定义了 JavaScript 操作浏览器的接口,提供了访问某些功能(如浏览器窗口大小.版 ...

  9. FastReport.Net使用:[27]样式使用

    样式设置与使用 1.打开样式设置界面,通过 报表->样式 来打开. 2.样式设置包含:边框,填充,字体和文本颜色.假如不需要某项设置,可将其选择框去掉. 3.设置好样式后,将标题的style设置 ...

  10. MongoDB——环境搭建

    项目中需要将一些读多改少的数据存入到 MongoDB 数据库中来提高效率,于是简单学习一些MongoDB数据库的知识,来进行应对,也是对自己知识盲区进行补充.本文主要学习介绍MongoDB数据库在Li ...