poj1222 EXTENDED LIGHTS OUT

5*6矩阵灯谜题解
本文介绍了一种解决5*6矩阵灯谜的方法,通过高斯消元算法找到最优解,避免了同时按下同一灯泡两次的情况,提供了一个有效的解决方案。

题目描述:

多组数据,每次给出一个$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;
}

 

转载于:https://www.cnblogs.com/LiGuanlin1124/p/10473887.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值