列表

详情


NC230527. EXTENDED LIGHTS OUT

描述

在 Lights Out 游戏的扩展版本中,是一个有 5 行每行 6 个按钮的谜题(实际的谜题有 5 行每行 5 个按钮)。每个按钮都有一个灯。当按下按钮时,该按钮及其上方、下方、右侧和左侧的每个(最多四个)相邻按钮的灯状态会反转。 (如果打开,灯关闭;如果关闭,灯打开。)角落的按钮改变3个按钮的状态;边缘的按钮改变4个按钮的状态,其他按钮改变5个的状态。例如,如果按下下方左侧标记为X的按钮,则显示将变为右侧的图像。

游戏的目标是,从显示器上的任何一组初始灯开始,按下按钮使显示器进入所有灯都关闭的状态。当相邻按钮被按下时,一个按钮的动作可以撤销另一个按钮的效果。例如,在下面的显示中,按下左侧显示中标记为 X 的按钮会导致右侧显示。注意,第 2 行第 3 列和第 2 行第 5 列的按钮都改变了第 2 行第 4 列按钮的状态,所以最后,它的状态是不变的。

笔记:
1. 按下按钮的顺序无关紧要。
2. 如果第二次按下按钮,它会完全取消第一次按下的效果,因此不需要多次按下按钮。
3. 如第二张图所示,按下第二排对应的按钮,可以关闭第一排的所有灯。通过在每一行重复这个过程,第一行中的所有灯
可能会出现四行。类似地,通过按下第 2、3 列中的按钮,可以关闭前 5 列中的所有灯。
编写一个程序来解决这个难题。

输入描述

输入的第一行是一个正整数 T,表示谜题个数。每个谜题将有5行,每行有6个数: 01,由一个空格分隔。 0 表示最初灯关闭,而 1 表示最初灯打开。

输出描述

对于每个谜题,输出:
第一行带有字符串:“PUZZLE #m”,其中 m 表示第m个谜题。
在该行之后,是一个类似拼图的显示(与输入格式相同)。在这种情况下,1 表示必须按下才能解谜的按钮,而 0 表示未按下的按钮。在类似拼图的输出显示中,每个 01 之间应该正好有一个空格。

示例1

输入:

2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0

输出:

PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0
PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 35ms, 内存消耗: 492K, 提交时间: 2022-10-05 17:41:01

#include<bits/stdc++.h>
using namespace std;
int d[5][2] = {{0,0},{0,1},{0,-1},{1,0},{-1,0}};
int n = 30, a[50][50],cnt,ans[6][6];
int IDX = 1;
void guess()
{
    for(int i=0;i<n;i++){
		int k=i;
		for(;k<n;k++) if(a[k][i]) break;
		for(int j=0;j<=n;j++) swap(a[i][j],a[k][j]);
		for(int j=0;j<n;j++){
		    if(i==j) continue;
		    if(a[j][i]) for(int k=i;k<=n;k++) a[j][k]^=a[i][k];
		}
	}
    for(int i=n-1;i>=0;i--) ans[i/6][i%6] = a[i][n];
    
}
void my()
{
    memset(a,0,sizeof a);
    for(int i=0;i<n;i++) cin>>a[i][n];
    for(int i=0;i<n;i++)
    {
        int x = i/6, y = i%6;
        for(int j=0;j<5;j++)
        {
            int nx = x+d[j][0],  ny = y + d[j][1];
            if(nx<0 || nx>=5 || ny<0 || ny>=6) continue;
            a[i][nx*6 + ny] = 1;
        }
    }
    guess();
    printf("PUZZLE #%d\n",IDX++);
    for(int i=0;i<5;i++)
    {
        for(int j=0;j<=5;j++)
        {
            cout<<ans[i][j]<<" ";
        }
        cout<<endl;
    }
}
signed main()
{
    int T = 1;
    cin>>T;
    while(T--)
    {
        my();
    }
}

C++ 解法, 执行用时: 12ms, 内存消耗: 520K, 提交时间: 2022-02-20 16:13:42

#include <iostream>
#include <algorithm>
using namespace std;

int cas, a[35], mp[10][10];

void solve()
{
	for (int i = 0; i < 5; i++)
		for (int j = 0; j < 6; j++)
			scanf("%d", &mp[i][j]);
	for (int i = 1; i <= 30; i++)
	{
		a[i] = 1 << i, a[i] ^= mp[(i - 1) / 6][(i - 1) % 6];
		if (i - 6 >= 1)a[i] ^= 1 << (i - 6);
		if (i + 6 < 31)a[i] ^= 1 << (i + 6);
		if (i % 6 != 1)a[i] ^= 1 << (i - 1);
		if (i % 6 != 0)a[i] ^= 1 << (i + 1);
	}
	for (int i = 1; i <= 30; i++)
	{
		int cur = i;
		while (cur <= 30 && !(a[cur] >> i & 1)) cur++;
		if (cur != i)swap(a[i], a[cur]);
		for (int j = 1; j <= 30; j++)
			if (i != j && a[j] >> i & 1)a[j] ^= a[i];
	}
	printf("PUZZLE #%d\n", ++cas);
	for (int i = 0; i < 5; i++, puts(""))
		for (int j = 1; j <= 6; j++)
			printf("%d ", a[i * 6 + j] & 1);
}

signed main()
{
	int t;
	cin >> t;
	while (t--)solve();
	return 0;
}

上一题