poj1222 EXTENDED LIGHTS OUT

题目描述:

多组数据,每次给出一个$5*6$的$01$矩阵,代表灯暗、灯亮。

你要关灯但是按下一个灯会影响上下左右。

求方案。

题解:

显然不可能按同一个灯泡两次。

高消搞一下。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,nam[10][10],a[35][35],ans[35];
int dx[5]={-1,1,0,0,0},dy[5]={0,0,1,-1,0};
void init()
{
    int tot = 0;
    for(int i=1;i<=5;i++)
        for(int j=1;j<=6;j++)
            nam[i][j]=++tot;
}
bool check(int x,int y)
{
    return x>=1&&x<=5&&y>=1&&y<=6;
}
int fre[35],tl;
int gs()
{
    int l1,l2;
    tl=0;
    for(l1=l2=1;l1<=30&&l2<=30;l1++,l2++)
    {
        int tmp = l1;
        for(int j=l1;j<=30;j++)
            if(abs(a[j][l2])>abs(a[tmp][l2]))tmp=j;
        if(tmp!=l1)
            for(int j=l2;j<=31;j++)swap(a[l1][j],a[tmp][j]);
        if(!a[l1][l2])
        {
            fre[++tl]=l2;
            l1--;
            continue;
        }
        for(int j=l1+1;j<=30;j++)
            if(a[j][l2])
                for(int k=l2;k<=31;k++)
                    a[j][k]^=a[l1][k];
    }
    for(int i=l1+1;i<=30;i++)
        if(a[i][31])return -1;
    if(l1<30)return 30-l1;
    for(int i=30;i>=1;i--)
    {
        ans[i]=a[i][31];
        for(int j=i-1;j>=1;j--)
            a[j][31]^=(a[i][31]&a[j][i]);
    }
}
int main()
{
    scanf("%d",&t);int tim=0;
    init();
    while(t--)
    {
        memset(a,0,sizeof(a));
        printf("PUZZLE #%d\n",++tim);
        for(int c,i=1;i<=5;i++)
            for(int j=1;j<=6;j++)
            {
                scanf("%d",&c);int u = nam[i][j];
                for(int x,y,k=0;k<5;k++)
                {
                    x = i+dx[k],y = j+dy[k];
                    if(!check(x,y))continue;
                    a[u][nam[x][y]]=1;
                }
                a[u][31]=c;
            }
        int k = gs();
        int u = 0;
        for(int i=1;i<=5;i++,puts(""))
            for(int j=1;j<=6;j++)
            {
                printf("%d ",ans[++u]);
            }
    }
    return 0;
}

 

posted @ 2019-03-04 22:48  LiGuanlin  阅读(113)  评论(0编辑  收藏  举报