POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题
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方程组来解决。
有时候需要枚举自由变元,有的是判断存不存在解
普通的问题。
肯定有唯一解。肯定枚举第一行去做,也可以使用高斯消元。
/* ***********************************************
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 ;
}
输出方案数,就是求出有多少个自由变元就可以了。
/* ***********************************************
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 ;
}
需要步数最少的,要枚举自由变元求解。
/* ***********************************************
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 ;
}
数据范围很小,随便搞,也是要枚举自由变元。。。。这题用高斯消元真是杀鸡用牛刀了
/* ***********************************************
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 ;
}
一维的了,更简单的还是枚举比较好。
高斯消元随便搞
/* ***********************************************
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 高斯消元求解一类开关问题的更多相关文章
- POJ 1681 Painter's Problem(高斯消元+枚举自由变元)
http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...
- POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total ...
- POJ 1830 开关问题(高斯消元求解的情况)
开关问题 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8714 Accepted: 3424 Description ...
- poj 1681 Painter's Problem(高斯消元)
id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
- POJ 1681 Painter's Problem (高斯消元 枚举自由变元求最小的步数)
题目链接 题意: 一个n*n 的木板 ,每个格子 都 可以 染成 白色和黄色,( 一旦我们对也个格子染色 ,他的上下左右 都将改变颜色): 给定一个初始状态 , 求将 所有的 格子 染成黄色 最少需要 ...
- POJ 1753 Flip game ( 高斯消元枚举自由变量)
题目链接 题意:给定一个4*4的矩阵,有两种颜色,每次反转一个颜色会反转他自身以及上下左右的颜色,问把他们全变成一种颜色的最少步数. 题解:4*4的矩阵打表可知一共有四个自由变元,枚举变元求最小解即可 ...
- poj 1753 Flip Game 高斯消元
题目链接 4*4的格子, 初始为0或1, 每次翻转一个会使它四周的也翻转, 求翻转成全0或全1最少的步数. #include <iostream> #include <vector& ...
- POJ 2065 高斯消元求解问题
题目大意: f[k] = ∑a[i]*k^i % p 每一个f[k]的值就是字符串上第 k 个元素映射的值,*代表f[k] = 0 , 字母代表f[k] = str[i]-'a'+1 把每一个k^i求 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)
[题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...
随机推荐
- 大数据系列之分布式数据库HBase-0.9.8安装及增删改查实践
若查看HBase-1.2.4版本内容及demo代码详见 大数据系列之分布式数据库HBase-1.2.4+Zookeeper 安装及增删改查实践 1. 环境准备: 1.需要在Hadoop启动正常情况下安 ...
- laravel 上传文件到亚马逊 aws s3
参考: https://github.com/aws/aws-sdk-php-laravel https://www.jianshu.com/p/e48d82bff20b
- U3D模拟仿真实现
最近在做一个模拟仿真系统,数据源是一个实时数据库,场景中包含一些监测点.监测点给信号的方式是有物体到了监测点给上料信号,物体离开了监测点给下料信号:注意,如果有多个物体到达或离开监测点,那给信号的时间 ...
- django时差8个小时问题
问题现象: 在用django做好的网站,上传图片后显示的发布时间比当前时间差了8小时 查找问题: 查看服务器系统时间,经查与当前时间一致,无问题 查看数据库中的时间也一样 最终原因: 在setting ...
- Python 一些 实用的包(持续更新)
line_profiler:(代码性能分析) 使用方法:链接 codecs:(Python内置的编码库) 数据分析与挖掘领域: 引自博客:这里 因为他有很多这个领域相关的库可以用,而且很好用, ...
- 关于ZIP自动打包的进一步进化思路
http://blog.163.com/long200259@126/blog/static/11288755920093120529157/
- es6 class 中 constructor 方法 和 super
首先,ES6 的 class 属于一种“语法糖”,所以只是写法更加优雅,更加像面对对象的编程,其思想和 ES5 是一致的. <1>constructor function Point(x, ...
- 【PAT】1003. 我要通过!(20)
1003. 我要通过!(20) “答案正确”是自动判题系统给出的最令人欢喜的回复.本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”. ...
- CentOS7.5 firefox Flash插件更新
CentOS7自带的firefox没有flash插件,所以是没有办法在网页上看视频的,需要自己手动安装 1.下载 打开flash官网https://get.adobe.com/flashplayer/ ...
- bzoj 1106
思路:很容易就能想到统计没两对点之间的未匹配点的个数. 在想怎么用数据结构维护这个东西, 没有想到用树状数组能很巧妙地维护出来, 就写了个莫队... 莫队:暴力维护就好了. #include<b ...