poj_1753_高斯消元

来源:互联网 发布:淘宝买家黑名单 编辑:程序博客网 时间:2024/06/01 17:04

开心,总算过了,对于高斯消元的理解更深一步,这道题的重点在于,如果用高斯消元的话,最后一行是要枚举的,总共16种情况,因为不知道怎么枚举,当时卡了好久,其实在线性方程组中,我们可以当做缺少了四个方程,所以我们的过程就是枚举最后四个方程,然后一步一步往回带入。
其中要注意一点,就是最后的结果可以全是白面,也可以全是黑面,看了很多博客,说的解法都很麻烦,其实大可以不必,只要a数组加两列就行,将枚举的结果回带的时候,要多开两个数组记录下解空间,仅此而已。

/*########################################################################## File Name: poj_1753.cpp# Author: CaoLei# Created Time: 2015/7/21 14:02:56#########################################################################*/#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>using namespace std;#define MAX(x,y) (((x)>(y))?(x):(y))#define MIN(x,y) (((x)<(y))?(x):(y))#define N 500010#define pi acos(-1.0)#define inf 100000000typedef long long ll;typedef unsigned long long ull;char str[10];int a[20][20];int x1[20];int x2[20];int gauss(){    //高斯消元基本过程    int i = 0, line = 0;    for (;i<16;){        int p = line;        for (int j = line + 1; j<16; j++) if (a[line][i]<a[j][i]) p = j;        if (p != line) for (int j = 0; j <= 17; j++) swap(a[line][j], a[p][j]);        if (a[line][i] == 0){            i++;            continue;        }        for (int j = 0; j<16; j++){            if (j != line&&a[j][i]){                for (int k = i; k <= 17; k++) a[j][k] ^= a[line][k];            }        }        i++;        line++;    }    bool f1 = true, f2 = true;    for (int k = line; k<16; k++){        if (a[k][16]) f1 = false;        if (a[k][17]) f2 = false;    }    if (!f1&&!f2) return -1;    if(line==16) return 1;    int ans=16;    //这里记录下自由元的个数    int t=16-line;    //枚举16种解的情况    for(int i=0;i<(1<<t);i++){        for(int j=0;j<16;j++){            x1[j]=a[j][16];            x2[j]=a[j][17];        }        for(int j=0;j<t;j++){            if(i&(1<<j)){                x1[15-j]=1;                x2[15-j]=1;            }            else {                x1[15-j]=0;                x2[15-j]=0;            }        }        //回带的过程        for(int j=16-t-1;j>=0;j--){            int tmp1=0,tmp2=0;            for(int k=j+1;k<16;k++){                if(a[j][k]) {                    tmp1^=x1[k];                    tmp2^=x2[k];                }            }            //维护解空间            x1[j]^=tmp1;            x2[j]^=tmp2;        }        int c1=0,c2=0;        for(int ii=0;ii<16;ii++){            if(x1[ii]) c1++;            if(x2[ii]) c2++;        }        //更新最小值        ans=MIN(ans,MIN(c1,c2));    }    return ans;}int main(){    //freopen("in.txt","r",stdin);    int nn=20;        memset(a,0,sizeof(a));        for (int i = 0; i<4; i++){            scanf("%s", str);            for (int j = 0; j<4; j++){                int tmp = i * 4 + j;                if (str[j] == 'b') {                    a[tmp][16] = 0;                    a[tmp][17] = 1;                }                else{                    a[tmp][16] = 1;                    a[tmp][17] = 0;                }                a[tmp][tmp] = 1;                if (tmp>3) a[tmp - 4][tmp] = 1;                if (tmp<12) a[tmp + 4][tmp] = 1;                if (tmp % 4 != 0) a[tmp - 1][tmp] = 1;                if (tmp % 4 != 3) a[tmp + 1][tmp] = 1;            }        }        int ans = gauss();        if (ans == -1) printf("Impossible\n");        else printf("%d\n", ans);    return 0;}
0 0
原创粉丝点击