POJ1681 高斯消元法 或者枚举 xingxing在努力

   这类开关问题一般都有两种解法, 一种是暴力枚举第一行 , 另外一种是列方程求解。。

   先附上暴力代码:

  

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int Map[20][20];    //y->0 w->1
int f[20][20];
int n;

int dx[5] = {0, 0, 0, 1, -1};
int dy[5] = {0, 1, -1, 0, 0};

int getcolor(int x, int y)
{
    int col = Map[x][y];
    for(int i=0; i<5; i++)
    {
        int nx = x+dx[i], ny = y+dy[i];
        if(nx>=0&&nx<n&&ny>=0&&ny<n)
            col += f[nx][ny];
    }
    return col%2;
}

int solve()    //返回值-1表示无解
{
    for(int i=1; i<n; i++)
        for(int j=0; j<n; j++)
            if(getcolor(i-1, j)==1) f[i][j] = 1;
    for(int j=0; j<n; j++)
        if(getcolor(n-1, j)==1) return -1;
    int res = 0;
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
        res += f[i][j];
    return res;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i=0; i<n; i++)
        {
            char s[20];
            scanf("%s", s);
            for(int j=0; j<n; j++)
                if(s[j]=='y') Map[i][j] = 0;
                else Map[i][j] = 1;
        }
        int res = -1;
        for(int i=0; i<(1<<n); i++)                     //暴力枚举第一行
        {
            memset(f, 0, sizeof(f));
            int st = i;
            for(int j=0; j<n; j++)      
            {
                if((st&1)==1) f[0][j] = 1;
                else f[0][j] = 0;
                st>>=1;
            }
            int tp = solve();
            if(tp >= 0)
            {
                if(res==-1) res = tp;
                else res = min(res, tp);
            }

        }
        if(res == -1)
            printf("inf\n");
        else
            printf("%d\n", res);
    }
    return 0;
}

 

 

另外一种则是高斯消元法:代码如下

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 300;
int n;
int a[maxn][maxn];             //增广矩阵
int x[maxn];                   //解空间
int free_x[maxn], free_num;    //自由元以及自由元的个数
int equ, var;                  //方程的数量 以及变量的个数

void debug()
{
    printf("debug -------------\n");
    for(int i=0; i<equ; i++)
    {
        for(int j=0; j<=var; j++)
            printf("%d ", a[i][j]);
        printf("\n");
    }
}

int gauss()
{
    free_num = 0;
    int k, col;         //当前处理的行(哪一个方程)和列(哪一个变量)
    for(k=0,col=0; k<equ&&col<var; k++,col++)
    {
        int max_r = k;      //第col列绝对值的最大值
        for(int i=k+1; i<equ; i++)
        {
            if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
        }
        if(max_r != k)  //交换第k行和第max_r行
        {
            for(int j=k; j<=var; j++) swap(a[k][j], a[max_r][j]);
        }

        if(a[k][col] == 0)    //说明该列以下全是0
        {
            k--;
            free_x[free_num++] = col;
            continue;
        }
        for(int i=k+1; i<equ; i++)
        {
            if(a[i][col] != 0)
                for(int j=col; j<=var; j++)
                a[i][j] ^= a[k][j];
        }
    }
    for(int i=k; i<equ; i++)
    {
        if(a[i][col] != 0 ) return -1;
    }
    int res = 0x3f3f3f3f;
    for(int i=0; i<(1<<(var-k)); i++)
    {
        int cnt = 0;
        int index = i;
        for(int j=0; j<var-k; j++)
        {
            x[free_x[j]] = (index&1);
            if(x[free_x[j]]) cnt++;
            index>>=1;
        }
        for(int j=k-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()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        memset(a, 0, sizeof(a));
        memset(x, 0, sizeof(x));
        for(int i=0; i<n; i++)
        {
            char s[30];
            scanf("%s", s);
            for(int j=0; j<n; j++)
                if(s[j]=='y') a[i*n+j][n*n] = 0;
                else a[i*n+j][n*n] = 1;
        }
        equ=n*n; var=n*n;
        for(int i=0; i<var; i++)
        {
            a[i][i] = 1;
            if(i%n!=0) a[i-1][i] = 1;
            if(i%n!=n-1) a[i+1][i] = 1;
            if(i>n-1) a[i-n][i] = 1;
            if(i<(n-1)*n) a[i+n][i] = 1;
        }
        //debug();
        int t = gauss();
        if(t == -1)
            printf("inf\n");
        else
            printf("%d\n", t);
    }
    return 0;
}

 

posted @ 2015-11-22 00:53  xing-xing  阅读(126)  评论(0)    收藏  举报