POJ 1681 (高斯消元)

来源:互联网 发布:战争程序员白濑 动漫 编辑:程序博客网 时间:2024/05/16 18:42

板子题,01方程求解,自由元取0不一定是最优的.

#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>using namespace std;#define maxn 333#define free Freeint a[maxn][maxn];char mp[maxn][maxn];int free[maxn*maxn]; //标记自由元int x[maxn*maxn], cnt; //解集 自由元个数int n;int Gauss () {    int max_r, col, k; //最大的数在的行 当前处理的列    cnt = 0; //自由元个数    for (k = 0, col = 0; k < n*n && col < n*n; k++, col++) {        max_r = k;        for (int i = k+1; i < n*n; i++) { //找到最大的数所在的行            if (abs (a[i][col]) > abs (a[max_r][col]))                max_r = i;        }        if (max_r != k) { //交换最大的数所在的行和当前行            for (int i = 0; i <= n*n; i++)                swap (a[k][i], a[max_r][i]);        }        if (a[k][col] == 0) { //判断自由元 处理当前行的下一列            k--;            free[cnt++] = col;            continue;        }        for (int i = k+1; i < n*n; i++) {            if (a[i][col]) {                for (int j = col; j <= n*n; j++) {                    a[i][j] ^= a[k][j];                }            }        }    }    for (int i = k; i < n*n; i++) { //判断无解情况        if (a[i][col])            return -1;    }    if (k < n*n)        return n*n - k; //返回自由元个数    for (int i = n*n-1; i >= 0; i--) { //回代        x[i] = a[i][n*n];        for (int j = i+1; j < n*n; j++)            x[i] ^= (a[i][j] && x[j]);    }    return 0;}void solve () {    memset (x, 0, sizeof x);    memset (free, 0, sizeof free);    int tot = Gauss ();    if (tot == -1) {        cout << "inf" << endl;        return ;    }    else if (tot == 0) {        int ans = 0;        for (int i = 0; i < n*n; i++)            ans += x[i];        cout << ans << endl;        return ;    }    else { //枚举自由元        int ans = 11111;        for (int i = 0; i < (1<<tot); i++) {            int num = 0;            for (int j = 0; j < tot; j++) {                if (i&(1<<j)) { //这一个自由元取1                    x[free[j]] = 1;                    num++;                }                else x[free[j]] = 0;            }            for (int j = n*n-tot-1; j >= 0; j--) { //计算所有的非自由元                int id;                for (id = j; id < n*n; id++)                    if (a[j][id])                        break;                x[id] = a[j][n*n];                for (int l = id+1; l < n*n; l++) if (a[j][l]) {                    x[id] ^= x[l];                }                num += x[id];            }            ans= min (ans, num);        }        cout << ans << endl;    }}int main () {    //freopen ("in", "r", stdin);    int t;    cin >> t;    while (t--) {        cin >> n;        memset (a, 0, sizeof a);        for (int i = 0; i < n; i++) {            cin >> mp[i];            for (int j = 0; j < n; j++) {                if (mp[i][j] == 'y')                    a[i*n+j][n*n] = 0;                else a[i*n+j][n*n] = 1;            }        }        for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {                a[i*n+j][i*n+j] = 1;                int pos = i*n+j;                if (i > 0)                    a[(i-1)*n+j][pos] = 1;                if (i < n-1)                    a[(i+1)*n+j][pos] = 1;                if (j > 0)                    a[pos-1][pos] = 1;                if (j < n-1)                    a[pos+1][pos] = 1;            }        }        solve ();    }    return 0;}


0 0