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,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...
随机推荐
- python脚本-实现自动按规则创建指定大小和指定个数的文件案例
# -*- coding: cp936 -*-#---------------------------------------------------------------------------- ...
- php pdo封装类
class MYPDO { protected static $_instance = null; protected $dbname = ''; protected $dsn; protected ...
- Eloquent中一些其他的create方法
firstOrCreate/ firstOrNew# 还有两种其它方法,你可以用来通过属性批量赋值创建你的模型:firstOrCreate 和firstOrNew.firstOrCreate 方法将会 ...
- laravel入门教程
参考地址:https://github.com/johnlui/Learn-Laravel-5/issues/16
- linux CentOS 上安装chrome
1.wget http://chrome.richardlloyd.org.uk/install_chrome.sh (用wget下载shell文件)2.chmod u+x install_chr ...
- C++输入与输出
1 概述 C和C++都没有将输入和输出建立在语言中,C++将输入输出的解决方案放在类库中(由头文件iostream和fstream中定义的类) C++程序把输入和输出看作字节流.流充当了程序和流源流目 ...
- controller中,Failed to Initialize. Reason: TimeOut虚拟用花初始化超时
1.调整 Run-timesetting->Internet Protocol->references->Advaanced->Options 将HTTP-request co ...
- bzoj 1415 期望dp + 记忆化搜索
思路:这个题看着感觉不能dp,其实是可以dp的,因为狼每次走两步,兔子每次走一步,每进行一轮以后,狼和兔子的距离 肯定是在接近的,没有相同的状态,dp之前预处理出来,每一步狼该往哪里走. #inclu ...
- 微信公共服务平台开发(.Net的实现)1 认证“成为开发者”
http://www.cnblogs.com/freeliver54/p/3725979.html http://www.it165.net/pro/html/201402/9459.html 这些代 ...
- SQL join关键字
如果一张表有很多个字段可能填入起来十分的困难复杂,不如把它拆分成两个表,然后查看的时候合并起来. 比如我要记录学生的姓名,班级,成绩,父母的电话号码,那么我们可以创建一个表1 储存学生的姓名班级成绩, ...