poj 1681 高斯消元 枚举自由元求翻转最小次
2015-08-03 23:54
363 查看
题意:
给一个n*n的矩阵,初始的时候是黄或者白的。
现在给染色,每个点染色的时候四周都会变黄。
求最少次数给这些点染色,将整个矩阵染成黄色。
解析:
与上题相比,这题要求最少的染色次数。
应该是上题的升级版。
首先抽象建立增广矩阵,然后是枚举自由元。
代码:
给一个n*n的矩阵,初始的时候是黄或者白的。
现在给染色,每个点染色的时候四周都会变黄。
求最少次数给这些点染色,将整个矩阵染成黄色。
解析:
与上题相比,这题要求最少的染色次数。
应该是上题的升级版。
首先抽象建立增广矩阵,然后是枚举自由元。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long using namespace std; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = 4 * atan(1.0); const double ee = exp(1.0); const int maxn = 1000 + 10; int a[maxn][maxn]; //增广矩阵 int x[maxn]; //解集 int freeX[maxn]; //记录自由变元在哪行 int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } int lcm(int a, int b) { return a / gcd(a, b) * b; } //高斯消元解方程组 //返回值-2表示有浮点数解,无整数解 //返回值-1表示无解,0表示有唯一解,大于0表示有无穷解,返回自由变元个数 //有equ个方程,var个变元 //增广矩阵行数[0, equ - 1] //增广矩阵列数[0, var] int gauss(int equ, int var) { int num = 0; for (int i = 0; i <= var; i++) { x[i] = 0; freeX[i] = 0; } //转换为阶梯矩阵 //col表示当前正在处理的这一列 int col = 0; int row = 0; //maxR表示当前这个列中元素绝对值最大的行 int maxRow; for (; row < equ && col < var; row++, col++) { //枚举当前正在处理的行 //找到该col列元素绝对值最大的那行与第k行交换 maxRow = row; for (int i = row + 1; i < equ; i++) { if (abs(a[maxRow][col]) < abs(a[i][col])) { maxRow = i; } } if (maxRow != row) { //与第row行交换 for (int j = row; j < var + 1; j++) { swap(a[row][j], a[maxRow][j]); } } if (a[row][col] == 0) { //说明该col列第row行以下全是0,处理当前行的下一列 row--; freeX[num++] = col; continue; } for (int i = row + 1; i < equ; i++) { //枚举要删的行 if (a[i][col] != 0) { for (int j = col; j < var + 1; j++) { /// a[i][j] ^= a[row][j]; } } } } for (int i = row; i < equ; i++) { if (a[i][col] != 0) { return -1; } } int state = 1 << (var - row); int res = inf; for (int i = 0; i < state; i++) { int cnt =0 ; int index = i; for (int j = 0; j < var - row; j++) { x[freeX[j]] = (index & 1); if (x[freeX[j]]) cnt++; index >>= 1; } for (int j = row - 1; j >= 0; j--) { int tmp = a[j][var]; for (int l = j + 1; l < var; l++) { if (a[j][l]) tmp ^= x[l]; } x[j] = tmp; if (x[j]) cnt++; } if (cnt < res) res = cnt; } return res; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; char g[20]; scanf("%d", &ncase); while (ncase--) { int n; scanf("%d", &n); int equ = n * n; int var = n * n; memset(a, 0, sizeof(a)); for (int i = 0; i < n; i++) { scanf("%s", &g); for (int j = 0; j < n; j++) { if (g[j] == 'y') { a[i * n + j][var] = 0; } else { a[i * n + j][var] = 1; } } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int t = i * n + j; a[t][t] = 1; if (i > 0) a[(i - 1) * n + j][t] = 1; if(i < n - 1) a[(i + 1) * n + j][t] = 1; if(j > 0) a[i * n + j - 1][t] = 1; if(j < n - 1) a[i * n + j + 1][t] = 1; } } int ans = gauss(equ, var); if (ans == -1) puts("inf"); else printf("%d\n", ans); } return 0; }
相关文章推荐
- C#中的i++和++i
- hdoj1113(字符串map应用)
- leetcode 71: Simplify Path
- HDU - 3416 Marriage Match IV (最大流)
- spring 事务传播属性
- Java学习笔记(九) Bitset
- android_菜单的创建_xUtils框架使用
- android屏幕适配
- 连接SSO CAS的代码示例
- FFmpeg源代码结构图 - 编码
- POJ_1986_Distance Queries(LCA+tarjan)
- 升级win10,提示(RAM)内存不足2G的解决办法,亲测可行
- poj 1840
- JDK动态代理浅析
- hd2553 N皇后问题
- UVA 11925 Generating Permutations 生成排列 (序列)
- git 的分支体系命令汇总
- SetTimeOut jquery的作用
- 设计模式01: Singleton 单例模式(创建型模式)
- NOJ 2079 Prime (莫比乌斯反演)