POJ1222 高斯消元 枚举 xingxing在努力

  关于本题, 有两种做法, 一种就是暴力枚举第一行的操作, 然后顺势确定下面2-5行的操作,最后看看最后一行是否满足要求即可。。代码如下

  

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

using namespace std;
int Map[10][10];
int f[10][10];
int dr[5] = {0, 0, -1, 1, 0};
int dc[5] = {1, -1, 0, 0, 0};
inline bool inside(int x, int y)
{
    return (x>=0&&x<5&&y>=0&&y<6);
}
int getcolor(int x, int y)                          //获取坐标(x, y)的状态   其与他自己和周围的四个方块有关
{
    int col = Map[x][y];
    for(int i=0; i<5; i++)
    {
        int nx=x+dr[i], ny=y+dc[i];
        if(inside(nx, ny)) col+=f[nx][ny];
    }
    return col%2;
}

bool solve()
{
    for(int i=1; i<5; i++)                           //根据第一行确定下面几行的操作
    {
        for(int j=0; j<6; j++)
            if(getcolor(i-1, j)==1) f[i][j] = 1;
    }
    bool res = true;
    for(int j=0; j<6; j++)                          //查看最后一行是不是全部关着
        if(getcolor(4, j)==1)
        {
            res = false;
            break;
        }
    return res;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int T, kase=0;
    scanf("%d", &T);
    while(T--)
    {
        //memset(f, 0, sizeof(0));                                 //wa出新高度了 ==
        for(int i=0; i<5; i++)
            for(int j=0; j<6; j++)
                scanf("%d", &Map[i][j]);
        for(int i=0; i<(1<<6); i++)                               //枚举第一行的操作
        {
            memset(f, 0, sizeof(f));                             //记得清0
            int st = i;
            for(int j=0; j<6; j++)
            {
                if((st&1)==1)  f[0][j]=1;
                else  f[0][j] = 0;
                st>>=1;
            }
            if(solve())
                break;
            //memset(f, 0, sizeof(f));
        }
        printf("PUZZLE #%d\n", ++kase);
        for(int i=0; i<5; i++)
        {
            for(int j=0; j<6; j++)
                printf("%d%c", f[i][j], j==5?'\n':' ');
        }
    }
    return 0;
}

 

  除了上面的方法外还有一种列方程的方法解决本题。代码如下

 

  

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


using namespace std;
int a[35][35];
int ans[35];

void gauss()
{
    for(int i=0; i<30; i++)                         //开始消第i个元
    {
        int k = i;        
        for(; k<30; k++)                           //找到一行,这一行的第i列不为0
            if(a[k][i]!=0) break;
        for(int j=0; j<=30; j++)                   //交换这一行和第i行
            swap(a[i][j], a[k][j]);
        for(int j=0; j<30; j++)                    //利用第i行消去其他行第i列的1
            if(i!=j && a[j][i])
            for(int k=0; k<=30; k++)
            a[j][k] = a[j][k] ^ a[i][k];
    }
    for(int i=0; i<30; i++)
        ans[i] = a[i][30];
}

int main()
{
    int T, kase=0;
    scanf("%d", &T);
    while(T--)
    {
        memset(a, 0, sizeof(a));
        for(int i=0; i<30; i++)
            scanf("%d", &a[i][30]);
        for(int i=0; i<30; i++)
        {
            a[i][i] = 1;
            if(i%6!=0) a[i-1][i] = 1;
            if(i%6!=5) a[i+1][i] = 1;
            if(i>5)  a[i-6][i] = 1;
            if(i<24) a[i+6][i] = 1;
        }
        gauss();
        printf("PUZZLE #%d\n",++kase);
        for(int i=0;i<30;i++)
        {
        printf("%d",ans[i]);
        if(i%6==5)
            printf("\n");
        else
            printf(" ");
        }
    }
    return 0;
}

 

posted @ 2015-11-20 19:27  xing-xing  阅读(136)  评论(0)    收藏  举报