首页 > 代码库 > NEFU 505 超级红与黑 (高斯消元)

NEFU 505 超级红与黑 (高斯消元)

题目链接

中文题,改下模板构造一下就能过了,数据有点水,不过还是需要自由变元枚举的。

 

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <queue>#include <vector>#include <map>#include <ctime>using namespace std;const int maxn=300;//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到varint 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=0;    for(k=0,col=0; k<equ&&col<var; k++,col++)    {        max_r=k;        for(int i=k+1; 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+1; j++)                swap(a[k][j],a[max_r][j]);        for(int i=k+1; i<equ; i++)        {            if(a[i][col])            {                for(int j=col; j<var+1; j++)                    a[i][j]^=a[k][j];            }        }    }    for(int i=k; i<equ; i++)        if(a[i][col])            return -1;    if(k<var) return var-k;    for(int i=var-1; i>=0; i--)    {        x[i]=a[i][var];        for(int j=i+1; j<var; j++)            x[i]^=(a[i][j]&&x[j]);    }    return 0;}int n,m;void init(){    memset(a,0,sizeof(a));    memset(x,0,sizeof(x));    equ=n*m;    var=n*m;    for(int i=0; i<n; i++)        for(int j=0; j<m; j++)        {            int t=i*m+j;            a[t][t]=1;            if(i>0) a[(i-1)*m+j][t]=1;            if(i<n-1) a[(i+1)*m+j][t]=1;            if(j>0) a[i*m+j-1][t]=1;            if(j<m-1) a[i*m+j+1][t]=1;            if(i>0&&j>0) a[(i-1)*m+j-1][t]=1;            if(i>0&&j<m-1) a[(i-1)*m+j+1][t]=1;            if(i<n-1&&j>0) a[(i+1)*m+j-1][t]=1;            if(i<n-1&&j<m-1) a[(i+1)*m+j+1][t]=1;        }}int solve(){    int t=gauss();    if(t==-1)    {        return -1;    }    else if(t==0)    {        int ans=0;        for(int i=0; i<n*m; i++)            ans+=x[i];        return ans;    }    else    {        //枚举自由变元        int ans=0x3f3f3f3f;        int tot=(1<<t);        for(int i=0; i<tot; i++)        {            int cnt=0;            for(int j=0; j<t; j++)            {                if(i&(1<<j)) //注意不是&&                {                    x[free_x[j]]=1;                    cnt++;                }                else x[free_x[j]]=0;            }            for(int j=var-t-1; j>=0; j--)            {                int idx;                for(idx=j; idx<var; idx++)                    if(a[j][idx])                        break;                x[idx]=a[j][var];                for(int l=idx+1; l<var; l++)                    if(a[j][l])                        x[idx]^=x[l];                cnt+=x[idx];            }            ans=min(ans,cnt);        }        return ans;    }}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        for(int i=0;i<n;i++)        for(int j=0;j<m;j++)        {            cin>>a[i*m+j][n*m];        }        int ans=solve();        if(ans==-1)        puts("no sovle!");        else        printf("%d\n",ans);    }    return 0;}

 

NEFU 505 超级红与黑 (高斯消元)